diff options
-rw-r--r-- | android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSasTest.java | 106 | ||||
-rw-r--r-- | android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java | 5 | ||||
-rw-r--r-- | android/olm-sdk/src/main/java/org/matrix/olm/OlmSAS.java | 153 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/Android.mk | 4 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/olm_jni.h | 1 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/olm_jni_helper.cpp | 5 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/olm_jni_helper.h | 1 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/olm_sas.cpp | 390 | ||||
-rw-r--r-- | android/olm-sdk/src/main/jni/olm_sas.h | 41 |
9 files changed, 705 insertions, 1 deletions
diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSasTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSasTest.java new file mode 100644 index 0000000..bbb50ae --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSasTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019 New Vector 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.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.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmSasTest { + + private static OlmManager mOlmManager; + + //Enable the native lib + @BeforeClass + public static void setUpClass() { + // load native librandomBytesOfLength + mOlmManager = new OlmManager(); + } + + @Test + public void testSASCode() { + OlmSAS aliceSas = null; + OlmSAS bobSas = null; + + try { + aliceSas = new OlmSAS(); + bobSas = new OlmSAS(); + + String alicePKey = aliceSas.getPublicKey(); + String bobPKey = bobSas.getPublicKey(); + + Log.e(OlmSasTest.class.getSimpleName(), "#### Alice pub Key is " + alicePKey); + Log.e(OlmSasTest.class.getSimpleName(), "#### Bob pub Key is " + bobPKey); + + aliceSas.setTheirPublicKey(bobPKey); + bobSas.setTheirPublicKey(alicePKey); + + int codeLength = 6; + byte[] alice_sas = aliceSas.generateShortCode("SAS", codeLength); + byte[] bob_sas = bobSas.generateShortCode("SAS", codeLength); + + Log.e(OlmSasTest.class.getSimpleName(), "#### Alice SAS is " + new String(alice_sas, "UTF-8")); + Log.e(OlmSasTest.class.getSimpleName(), "#### Bob SAS is " + new String(bob_sas, "UTF-8")); + + assertEquals(codeLength, alice_sas.length); + assertEquals(codeLength, bob_sas.length); + assertArrayEquals(alice_sas, bob_sas); + + String aliceMac = aliceSas.calculateMac("Hello world!", "SAS"); + String bobMac = bobSas.calculateMac("Hello world!", "SAS"); + + assertEquals(aliceMac, bobMac); + + Log.e(OlmSasTest.class.getSimpleName(), "#### Alice Mac is " + aliceMac); + Log.e(OlmSasTest.class.getSimpleName(), "#### Bob Mac is " + bobMac); + + + String aliceLongKdfMac = aliceSas.calculateMacLongKdf("Hello world!", "SAS"); + String bobLongKdfMac = bobSas.calculateMacLongKdf("Hello world!", "SAS"); + + assertEquals("Mac should be the same", aliceLongKdfMac, bobLongKdfMac); + + Log.e(OlmSasTest.class.getSimpleName(), "#### Alice lkdf Mac is " + aliceLongKdfMac); + Log.e(OlmSasTest.class.getSimpleName(), "#### Bob lkdf Mac is " + bobLongKdfMac); + + + } catch (Exception e) { + assertTrue("OlmSas init failed " + e.getMessage(), false); + e.printStackTrace(); + } finally { + if (aliceSas != null) { + aliceSas.releaseSas(); + } + if (bobSas != null) { + bobSas.releaseSas(); + } + } + } + +} 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 532f318..5b4a85a 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 @@ -76,6 +76,11 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_PK_SIGNING_INIT_WITH_SEED = 802; public static final int EXCEPTION_CODE_PK_SIGNING_SIGN = 803; + public static final int EXCEPTION_CODE_SAS_CREATION = 900; + public static final int EXCEPTION_CODE_SAS_ERROR = 901; + public static final int EXCEPTION_CODE_SAS_MISSING_THEIR_PKEY = 902; + public static final int EXCEPTION_CODE_SAS_GENERATE_SHORT_CODE = 903; + // 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/OlmSAS.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmSAS.java new file mode 100644 index 0000000..4bd1579 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmSAS.java @@ -0,0 +1,153 @@ +/* + * Copyright 2019 New Vector 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.util.Log; + +import java.io.UnsupportedEncodingException; + +public class OlmSAS { + + private static final String LOG_TAG = OlmSAS.class.getName(); + /** + * Session Id returned by JNI. + * This value uniquely identifies the native SAS instance. + **/ + private transient long mNativeId; + + private String theirPublicKey = null; + + public OlmSAS() throws OlmException { + try { + mNativeId = createNewSASJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_CREATION, e.getMessage()); + } + } + + /** + * Gets the Public Key encoded in Base64 with no padding + */ + public String getPublicKey() throws OlmException { + try { + byte[] buffer = getPubKeyJni(); + + if (null != buffer) { + return new String(buffer, "UTF-8"); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage()); + } + + return null; + } + + /** + * Sets the public key of other user. + * + * @param otherPkey other user public key (base64 encoded with no padding) + * @throws OlmException + */ + public void setTheirPublicKey(String otherPkey) throws OlmException { + try { + setTheirPubKey(otherPkey.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage()); + } + this.theirPublicKey = otherPkey; + } + + + /** + * Generate bytes to use for the short authentication string. + * + * @param info info extra information to mix in when generating the bytes, as + * per the Matrix spec. + * @param byteNumber The size of the short code to generate + * @return The generated shortcode + * @throws OlmException + */ + public byte[] generateShortCode(String info, int byteNumber) throws OlmException { + if (theirPublicKey == null || theirPublicKey.isEmpty()) { + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_MISSING_THEIR_PKEY, "call setTheirPublicKey first"); + } + try { + return generateShortCodeJni(info.getBytes("UTF-8"), byteNumber); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_GENERATE_SHORT_CODE, e.getMessage()); + } + } + + + public String calculateMac(String message, String info) throws OlmException { + try { + byte[] bytes = calculateMacJni(message.getBytes("UTF-8"), info.getBytes("UTF-8")); + if (bytes != null) return new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage()); + } + return null; + } + + public String calculateMacLongKdf(String message, String info) throws OlmException { + try { + byte[] bytes = calculateMacLongKdfJni(message.getBytes("UTF-8"), info.getBytes("UTF-8")); + if (bytes != null) return new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage()); + } + return null; + } + + /** + * Create an OLM session in native side.<br> + * Do not forget to call {@link #releaseSASJni()} when JAVA side is done. + * + * @return native account instance identifier or throw an exception. + */ + private native long createNewSASJni(); + + /** + * Destroy the corresponding OLM 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 #createNewSASJni()}. + */ + private native void releaseSASJni(); + + private native byte[] getPubKeyJni(); + + private native void setTheirPubKey(byte[] pubKey); + + private native byte[] generateShortCodeJni(byte[] info, int byteNumber); + + private native byte[] calculateMacJni(byte[] message, byte[] info); + + private native byte[] calculateMacLongKdfJni(byte[] message, byte[] info); + + /** + * Release native session and invalid its JAVA reference counter part.<br> + * Public API for {@link #releaseSASJni()}. + */ + public void releaseSas() { + if (0 != mNativeId) { + releaseSASJni(); + } + mNativeId = 0; + } +} diff --git a/android/olm-sdk/src/main/jni/Android.mk b/android/olm-sdk/src/main/jni/Android.mk index 0d98f69..101346b 100644 --- a/android/olm-sdk/src/main/jni/Android.mk +++ b/android/olm-sdk/src/main/jni/Android.mk @@ -41,6 +41,7 @@ $(SRC_ROOT_DIR)/src/ratchet.cpp \ $(SRC_ROOT_DIR)/src/session.cpp \ $(SRC_ROOT_DIR)/src/utility.cpp \ $(SRC_ROOT_DIR)/src/pk.cpp \ +$(SRC_ROOT_DIR)/src/sas.c \ $(SRC_ROOT_DIR)/src/ed25519.c \ $(SRC_ROOT_DIR)/src/error.c \ $(SRC_ROOT_DIR)/src/inbound_group_session.c \ @@ -57,7 +58,8 @@ olm_inbound_group_session.cpp \ olm_outbound_group_session.cpp \ olm_utility.cpp \ olm_manager.cpp \ -olm_pk.cpp +olm_pk.cpp \ +olm_sas.cpp LOCAL_LDLIBS := -llog diff --git a/android/olm-sdk/src/main/jni/olm_jni.h b/android/olm-sdk/src/main/jni/olm_jni.h index 0a50c5f..110f089 100644 --- a/android/olm-sdk/src/main/jni/olm_jni.h +++ b/android/olm-sdk/src/main/jni/olm_jni.h @@ -73,6 +73,7 @@ struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); struct OlmPkDecryption* getPkDecryptionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); struct OlmPkEncryption* getPkEncryptionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); struct OlmPkSigning* getPkSigningInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmSAS* getOlmSasInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); #ifdef __cplusplus } diff --git a/android/olm-sdk/src/main/jni/olm_jni_helper.cpp b/android/olm-sdk/src/main/jni/olm_jni_helper.cpp index f13c5e1..47f83a8 100644 --- a/android/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/android/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -227,3 +227,8 @@ struct OlmPkSigning* getPkSigningInstanceId(JNIEnv* aJniEnv, jobject aJavaObject { return (struct OlmPkSigning*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_PK_SIGNING); } + +struct OlmSAS* getOlmSasInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmSAS*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SAS); +} diff --git a/android/olm-sdk/src/main/jni/olm_jni_helper.h b/android/olm-sdk/src/main/jni/olm_jni_helper.h index e9c03c8..22552b4 100644 --- a/android/olm-sdk/src/main/jni/olm_jni_helper.h +++ b/android/olm-sdk/src/main/jni/olm_jni_helper.h @@ -28,4 +28,5 @@ namespace AndroidOlmSdk static const char *CLASS_OLM_PK_ENCRYPTION = "org/matrix/olm/OlmPkEncryption"; static const char *CLASS_OLM_PK_DECRYPTION = "org/matrix/olm/OlmPkDecryption"; static const char *CLASS_OLM_PK_SIGNING = "org/matrix/olm/OlmPkSigning"; + static const char *CLASS_OLM_SAS = "org/matrix/olm/OlmSAS"; } diff --git a/android/olm-sdk/src/main/jni/olm_sas.cpp b/android/olm-sdk/src/main/jni/olm_sas.cpp new file mode 100644 index 0000000..400934f --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_sas.cpp @@ -0,0 +1,390 @@ +/* + * Copyright 2019 New Vector 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_sas.h" + +#include "olm/olm.h" + +using namespace AndroidOlmSdk; + +JNIEXPORT jlong OLM_SAS_FUNC_DEF(createNewSASJni)(JNIEnv *env, jobject thiz) +{ + + size_t sasSize = olm_sas_size(); + OlmSAS *sasPtr = (OlmSAS *) malloc(sasSize); + const char* errorMessage = NULL; + + if (!sasPtr) + { + LOGE("## createNewSASJni(): failure - init SAS OOM"); + env->ThrowNew(env->FindClass("java/lang/Exception"), "init sas OOM"); + } + else + { + sasPtr = olm_sas(sasPtr) + LOGD(" ## createNewSASJni(): success - sasPtr=%p (jlong)(intptr_t)accountPtr=%lld",sasPtr,(jlong)(intptr_t)sasPtr); + } + + size_t randomSize = olm_create_sas_random_length(sasPtr); + uint8_t *randomBuffPtr = NULL; + + LOGD("## createNewSASJni(): randomSize=%lu",static_cast<long unsigned int>(randomSize)); + + if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) + { + LOGE("## createNewSASJni(): failure - random buffer init"); + errorMessage = "Failed to init private key"; + } + else + { + size_t result = olm_create_sas(sasPtr, randomBuffPtr, randomSize); + if (result == olm_error()) + { + errorMessage = (const char *)olm_sas_last_error(sasPtr); + LOGE("## createNewSASJni(): failure - error creating SAS Msg=%s", errorMessage); + } + } + + if (randomBuffPtr) + { + memset(randomBuffPtr, 0, randomSize); + free(randomBuffPtr); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sasPtr; +} + +JNIEXPORT void OLM_SAS_FUNC_DEF(releaseSASJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## releaseSASJni(): IN"); + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + if (!sasPtr) + { + LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); + } + else + { + olm_clear_sas(sasPtr); + // even if free(NULL) does not crash, logs are performed for debug purpose + free(sasPtr); + } +} + + +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(getPubKeyJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## getPubKeyJni(): IN"); + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + if (!sasPtr) + { + LOGE("## getPubKeyJni(): failure - invalid SAS ptr=NULL"); + errorMessage = "invalid SAS ptr=NULL"; + } + else + { + size_t pubKeyLength = olm_sas_pubkey_length(sasPtr); + void *pubkey = malloc(pubKeyLength*sizeof(uint8_t)); + size_t result = olm_sas_get_pubkey(sasPtr, pubkey, pubKeyLength); + if (result == olm_error()) + { + errorMessage = (const char *)olm_sas_last_error(sasPtr); + LOGE("## getPubKeyJni(): failure - error getting pub key Msg=%s", errorMessage); + } + else + { + returnValue = env->NewByteArray(pubKeyLength); + env->SetByteArrayRegion(returnValue, 0 , pubKeyLength, (jbyte*)pubkey); + } + if (pubkey) { + free(pubkey); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKeyBuffer) { + + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + const char* errorMessage = NULL; + jbyte *pubKeyPtr = NULL; + jboolean pubKeyWasCopied = JNI_FALSE; + + if (!sasPtr) + { + LOGE("## setTheirPubKey(): failure - invalid SAS ptr=NULL"); + errorMessage = "invalid SAS ptr=NULL"; + } else if(!pubKeyBuffer) { + LOGE("## setTheirPubKey(): failure - invalid info"); + errorMessage = "invalid pubKey"; + } + else if (!(pubKeyPtr = env->GetByteArrayElements(pubKeyBuffer, &pubKeyWasCopied))) + { + LOGE(" ## setTheirPubKey(): failure - info JNI allocation OOM"); + errorMessage = "info JNI allocation OOM"; + } + else + { + size_t pubKeyLength = (size_t)env->GetArrayLength(pubKeyBuffer); + size_t result = olm_sas_set_their_key(sasPtr,pubKeyPtr,pubKeyLength); + if (result == olm_error()) + { + errorMessage = (const char *)olm_sas_last_error(sasPtr); + LOGE("## setTheirPubKey(): failure - error setting their key Msg=%s", errorMessage); + } + } + // free alloc + if (pubKeyPtr) + { + if (pubKeyWasCopied) + { + memset(pubKeyPtr, 0, (size_t)env->GetArrayLength(pubKeyBuffer)); + } + env->ReleaseByteArrayElements(pubKeyBuffer, pubKeyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + +} + +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb) { + LOGD("## generateShortCodeJni(): IN"); + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + jbyte *infoPtr = NULL; + jboolean infoWasCopied = JNI_FALSE; + + if (!sasPtr) + { + LOGE("## generateShortCodeJni(): failure - invalid SAS ptr=NULL"); + errorMessage = "invalid SAS ptr=NULL"; + } else if(!infoStringBytes) { + LOGE("## generateShortCodeJni(): failure - invalid info"); + errorMessage = "invalid info"; + } + else if (!(infoPtr = env->GetByteArrayElements(infoStringBytes, &infoWasCopied))) + { + LOGE(" ## generateShortCodeJni(): failure - info JNI allocation OOM"); + errorMessage = "info JNI allocation OOM"; + } + else { + size_t shortBytesCodeLength = (size_t) byteNb; + void *shortBytesCode = malloc(shortBytesCodeLength * sizeof(uint8_t)); + size_t infoLength = (size_t)env->GetArrayLength(infoStringBytes); + olm_sas_generate_bytes(sasPtr, infoPtr, infoLength, shortBytesCode, shortBytesCodeLength); + returnValue = env->NewByteArray(shortBytesCodeLength); + env->SetByteArrayRegion(returnValue, 0 , shortBytesCodeLength, (jbyte*)shortBytesCode); + free(shortBytesCode); + } + + // free alloc + if (infoPtr) + { + if (infoWasCopied) + { + memset(infoPtr, 0, (size_t)env->GetArrayLength(infoStringBytes)); + } + env->ReleaseByteArrayElements(infoStringBytes, infoPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + + +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) { + LOGD("## calculateMacJni(): IN"); + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + jbyte *messagePtr = NULL; + jboolean messageWasCopied = JNI_FALSE; + + jbyte *infoPtr = NULL; + jboolean infoWasCopied = JNI_FALSE; + + if (!sasPtr) + { + LOGE("## calculateMacJni(): failure - invalid SAS ptr=NULL"); + errorMessage = "invalid SAS ptr=NULL"; + } else if(!messageBuffer) { + LOGE("## calculateMacJni(): failure - invalid message"); + errorMessage = "invalid info"; + } + else if (!(messagePtr = env->GetByteArrayElements(messageBuffer, &messageWasCopied))) + { + LOGE(" ## calculateMacJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; + } + else if (!(infoPtr = env->GetByteArrayElements(infoBuffer, &infoWasCopied))) + { + LOGE(" ## calculateMacJni(): failure - info JNI allocation OOM"); + errorMessage = "info JNI allocation OOM"; + } else { + + size_t infoLength = (size_t)env->GetArrayLength(infoBuffer); + size_t messageLength = (size_t)env->GetArrayLength(messageBuffer); + size_t macLength = olm_sas_mac_length(sasPtr); + + void *macPtr = malloc(macLength*sizeof(uint8_t)); + + size_t result = olm_sas_calculate_mac(sasPtr,messagePtr,messageLength,infoPtr,infoLength,macPtr,macLength); + if (result == olm_error()) + { + errorMessage = (const char *)olm_sas_last_error(sasPtr); + LOGE("## calculateMacJni(): failure - error calculating SAS mac Msg=%s", errorMessage); + } + else + { + returnValue = env->NewByteArray(macLength); + env->SetByteArrayRegion(returnValue, 0 , macLength, (jbyte*)macPtr); + } + + if (macPtr) { + free(macPtr); + } + } + + // free alloc + if (infoPtr) + { + if (infoWasCopied) + { + memset(infoPtr, 0, (size_t)env->GetArrayLength(infoBuffer)); + } + env->ReleaseByteArrayElements(infoBuffer, infoPtr, JNI_ABORT); + } + if (messagePtr) + { + if (messageWasCopied) + { + memset(messagePtr, 0, (size_t)env->GetArrayLength(messageBuffer)); + } + env->ReleaseByteArrayElements(messageBuffer, messagePtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) { + LOGD("## calculateMacLongKdfJni(): IN"); + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz); + + jbyte *messagePtr = NULL; + jboolean messageWasCopied = JNI_FALSE; + + jbyte *infoPtr = NULL; + jboolean infoWasCopied = JNI_FALSE; + + if (!sasPtr) + { + LOGE("## calculateMacLongKdfJni(): failure - invalid SAS ptr=NULL"); + errorMessage = "invalid SAS ptr=NULL"; + } else if(!messageBuffer) { + LOGE("## calculateMacLongKdfJni(): failure - invalid message"); + errorMessage = "invalid info"; + } + else if (!(messagePtr = env->GetByteArrayElements(messageBuffer, &messageWasCopied))) + { + LOGE(" ## calculateMacLongKdfJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; + } + else if (!(infoPtr = env->GetByteArrayElements(infoBuffer, &infoWasCopied))) + { + LOGE(" ## calculateMacLongKdfJni(): failure - info JNI allocation OOM"); + errorMessage = "info JNI allocation OOM"; + } else { + + size_t infoLength = (size_t)env->GetArrayLength(infoBuffer); + size_t messageLength = (size_t)env->GetArrayLength(messageBuffer); + size_t macLength = olm_sas_mac_length(sasPtr); + + void *macPtr = malloc(macLength*sizeof(uint8_t)); + + size_t result = olm_sas_calculate_mac_long_kdf(sasPtr,messagePtr,messageLength,infoPtr,infoLength,macPtr,macLength); + if (result == olm_error()) + { + errorMessage = (const char *)olm_sas_last_error(sasPtr); + LOGE("## calculateMacLongKdfJni(): failure - error calculating SAS mac Msg=%s", errorMessage); + } + else + { + returnValue = env->NewByteArray(macLength); + env->SetByteArrayRegion(returnValue, 0 , macLength, (jbyte*)macPtr); + } + + if (macPtr) { + free(macPtr); + } + } + + // free alloc + if (infoPtr) + { + if (infoWasCopied) + { + memset(infoPtr, 0, (size_t)env->GetArrayLength(infoBuffer)); + } + env->ReleaseByteArrayElements(infoBuffer, infoPtr, JNI_ABORT); + } + if (messagePtr) + { + if (messageWasCopied) + { + memset(messagePtr, 0, (size_t)env->GetArrayLength(messageBuffer)); + } + env->ReleaseByteArrayElements(messageBuffer, messagePtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +}
\ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_sas.h b/android/olm-sdk/src/main/jni/olm_sas.h new file mode 100644 index 0000000..3340459 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_sas.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 New Vector 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 _OMLSAS_H +#define _OMLSAS_H + +#include "olm_jni.h" +#include "olm/sas.h" + +#define OLM_SAS_FUNC_DEF(func_name) FUNC_DEF(OlmSAS,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jlong OLM_SAS_FUNC_DEF(createNewSASJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_SAS_FUNC_DEF(releaseSASJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(getPubKeyJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKey); +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb); +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer); +JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer); + +#ifdef __cplusplus +} +#endif + +#endif |