From d9cd17c26b4d130ef0397563c32f60971e193120 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 13 May 2020 14:35:47 +0200 Subject: [PATCH 1/5] Version++ --- CHANGES.rst | 27 +++++++++++++++++++++++++++ matrix-sdk/build.gradle | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 840fb6b5c..c25037f42 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,30 @@ +Changes to Matrix Android SDK in 0.9.35 (2020-XX-XX) +======================================================= + +Features: + - + +Improvements: + - + +Bugfix: + - + +API Change: + - + +Translations: + - + +Others: + - + +Build: + - + +Test: + - + Changes to Matrix Android SDK in 0.9.34 (2020-05-13) ======================================================= diff --git a/matrix-sdk/build.gradle b/matrix-sdk/build.gradle index f4d8c7b3a..21cb31049 100644 --- a/matrix-sdk/build.gradle +++ b/matrix-sdk/build.gradle @@ -27,8 +27,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 28 - versionCode 934 - versionName "0.9.34" + versionCode 935 + versionName "0.9.35-dev" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Enable multi dex for test From e2f9094a3268df38b84230267615498d4d684a8f Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 19 May 2020 12:20:41 +0200 Subject: [PATCH 2/5] sas_v2 --- CHANGES.rst | 2 +- .../IncomingSASVerificationTransaction.kt | 46 ++++++++++----- .../OutgoingSASVerificationRequest.kt | 48 ++++++++++----- .../SASVerificationTransaction.kt | 7 ++- .../androidsdk/crypto/verification/SASTest.kt | 58 +++++++++++++++++++ 5 files changed, 129 insertions(+), 32 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c25037f42..798dcbdae 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -17,7 +17,7 @@ Translations: - Others: - - + - support new key agreement method for SAS (riotX/#1374) Build: - diff --git a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt index 93a932cdf..88837c8f1 100644 --- a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt +++ b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt @@ -184,21 +184,7 @@ class IncomingSASVerificationTransaction(transactionId: String, otherUserID: Str // using the result as the shared secret. getSAS().setTheirPublicKey(otherKey) - //(Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function, - // the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of: - // - the string “MATRIX_KEY_VERIFICATION_SAS”, - // - the Matrix ID of the user who sent the m.key.verification.start message, - // - the device ID of the device that sent the m.key.verification.start message, - // - the Matrix ID of the user who sent the m.key.verification.accept message, - // - he device ID of the device that sent the m.key.verification.accept message - // - the transaction ID. - val sasInfo = "MATRIX_KEY_VERIFICATION_SAS" + - "$otherUserId$otherDeviceId" + - "${session.myUserId}${session.requireCrypto().myDevice.deviceId}" + - transactionId - //decimal: generate five bytes by using HKDF. - //emoji: generate six bytes by using HKDF. - shortCodeBytes = getSAS().generateShortCode(sasInfo, 6) + shortCodeBytes = calculateSASBytes(session) Log.e(LOG_TAG, "************ BOB CODE ${getDecimalCodeRepresentation(shortCodeBytes!!)}") Log.e(LOG_TAG, "************ BOB EMOJI CODE ${getShortCodeRepresentation(KeyVerificationStart.SAS_MODE_EMOJI)}") @@ -206,6 +192,36 @@ class IncomingSASVerificationTransaction(transactionId: String, otherUserID: Str state = SASVerificationTxState.ShortCodeReady } + private fun calculateSASBytes(session: CryptoSession): ByteArray { + val myDeviceId = session.requireCrypto().myDevice.deviceId + when (accepted?.keyAgreementProtocol) { + KEY_AGREEMENT_V1 -> { + // (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function, + // the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of: + // - the string “MATRIX_KEY_VERIFICATION_SAS”, + // - the Matrix ID of the user who sent the m.key.verification.start message, + // - the device ID of the device that sent the m.key.verification.start message, + // - the Matrix ID of the user who sent the m.key.verification.accept message, + // - he device ID of the device that sent the m.key.verification.accept message + // - the transaction ID. + val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$otherUserId$otherDeviceId${session.myUserId}$myDeviceId$transactionId" + + // decimal: generate five bytes by using HKDF. + // emoji: generate six bytes by using HKDF. + return getSAS().generateShortCode(sasInfo, 6) + } + KEY_AGREEMENT_V2 -> { + // Adds the SAS public key, and separate by | + val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|$otherUserId|$otherDeviceId|$otherKey|${session.myUserId}|$myDeviceId|${getSAS().publicKey}|$transactionId" + return getSAS().generateShortCode(sasInfo, 6) + } + else -> { + // Protocol has been checked earlier + throw IllegalArgumentException() + } + } + } + override fun onKeyVerificationMac(session: CryptoSession, vKey: KeyVerificationMac) { Log.d(LOG_TAG, "## SAS received mac for request id:$transactionId") //Check for state? diff --git a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/OutgoingSASVerificationRequest.kt b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/OutgoingSASVerificationRequest.kt index d9af19776..787f9400a 100644 --- a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/OutgoingSASVerificationRequest.kt +++ b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/OutgoingSASVerificationRequest.kt @@ -156,21 +156,7 @@ class OutgoingSASVerificationRequest(transactionId: String, otherUserId: String, if (accepted!!.commitment.equals(otherCommitment)) { getSAS().setTheirPublicKey(otherKey) - //(Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function, - // the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of: - // - the string “MATRIX_KEY_VERIFICATION_SAS”, - // - the Matrix ID of the user who sent the m.key.verification.start message, - // - the device ID of the device that sent the m.key.verification.start message, - // - the Matrix ID of the user who sent the m.key.verification.accept message, - // - he device ID of the device that sent the m.key.verification.accept message - // - the transaction ID. - val sasInfo = "MATRIX_KEY_VERIFICATION_SAS" + - "${session.myUserId}${session.requireCrypto().myDevice.deviceId}" + - "$otherUserId$otherDeviceId" + - transactionId - //decimal: generate five bytes by using HKDF. - //emoji: generate six bytes by using HKDF. - shortCodeBytes = getSAS().generateShortCode(sasInfo, 6) + shortCodeBytes = calculateSASBytes(session) state = SASVerificationTxState.ShortCodeReady } else { //bad commitement @@ -178,6 +164,38 @@ class OutgoingSASVerificationRequest(transactionId: String, otherUserId: String, } } + + private fun calculateSASBytes(session: CryptoSession): ByteArray { + val userId = session.myUserId + val deviceId = session.requireCrypto().myDevice.deviceId + when (accepted?.keyAgreementProtocol) { + KEY_AGREEMENT_V1 -> { + // (Note: In all of the following HKDF is as defined in RFC 5869, and uses the previously agreed-on hash function as the hash function, + // the shared secret as the input keying material, no salt, and with the input parameter set to the concatenation of: + // - the string “MATRIX_KEY_VERIFICATION_SAS”, + // - the Matrix ID of the user who sent the m.key.verification.start message, + // - the device ID of the device that sent the m.key.verification.start message, + // - the Matrix ID of the user who sent the m.key.verification.accept message, + // - he device ID of the device that sent the m.key.verification.accept message + // - the transaction ID. + val sasInfo = "MATRIX_KEY_VERIFICATION_SAS$userId$deviceId$otherUserId$otherDeviceId$transactionId" + + // decimal: generate five bytes by using HKDF. + // emoji: generate six bytes by using HKDF. + return getSAS().generateShortCode(sasInfo, 6) + } + KEY_AGREEMENT_V2 -> { + // Adds the SAS public key, and separate by | + val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|$userId|$deviceId|${getSAS().publicKey}|$otherUserId|$otherDeviceId|$otherKey|$transactionId" + return getSAS().generateShortCode(sasInfo, 6) + } + else -> { + // Protocol has been checked earlier + throw IllegalArgumentException() + } + } + } + override fun onKeyVerificationMac(session: CryptoSession, vKey: KeyVerificationMac) { Log.d(LOG_TAG, "## onKeyVerificationMac id:$transactionId") if (state != SASVerificationTxState.OnKeyReceived diff --git a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/SASVerificationTransaction.kt b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/SASVerificationTransaction.kt index 093d9d5b1..d5f41d390 100644 --- a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/SASVerificationTransaction.kt +++ b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/SASVerificationTransaction.kt @@ -44,8 +44,13 @@ abstract class SASVerificationTransaction(transactionId: String, const val SAS_MAC_SHA256_LONGKDF = "hmac-sha256" const val SAS_MAC_SHA256 = "hkdf-hmac-sha256" + + // Deprecated maybe removed later, use V2 + const val KEY_AGREEMENT_V1 = "curve25519" + const val KEY_AGREEMENT_V2 = "curve25519-hkdf-sha256" + //ordered by preferred order - val KNOWN_AGREEMENT_PROTOCOLS = listOf(MXKey.KEY_CURVE_25519_TYPE) + val KNOWN_AGREEMENT_PROTOCOLS = listOf(KEY_AGREEMENT_V2, KEY_AGREEMENT_V1) //ordered by preferred order val KNOWN_HASHES = listOf("sha256") //ordered by preferred order diff --git a/matrix-sdk/src/androidTest/java/org/matrix/androidsdk/crypto/verification/SASTest.kt b/matrix-sdk/src/androidTest/java/org/matrix/androidsdk/crypto/verification/SASTest.kt index 48efd2f4b..33d4f409a 100644 --- a/matrix-sdk/src/androidTest/java/org/matrix/androidsdk/crypto/verification/SASTest.kt +++ b/matrix-sdk/src/androidTest/java/org/matrix/androidsdk/crypto/verification/SASTest.kt @@ -193,6 +193,63 @@ class SASTest { } + @Test + fun test_key_agreement_protocols_v1() { + val context = InstrumentationRegistry.getContext() + + val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom() + + val bobSession = cryptoTestData.secondSession + + val protocols = listOf(SASVerificationTransaction.KEY_AGREEMENT_V1) + val tid = "00000000" + + //Bob should receive a cancel + var acceptToDeviceEvent: Event? = null + val cancelLatch = CountDownLatch(1) + bobSession!!.dataHandler.addListener(object : MXEventListener() { + override fun onToDeviceEvent(event: Event?) { + if (event!!.getType() == CryptoEvent.EVENT_TYPE_KEY_VERIFICATION_ACCEPT) { + if (event.contentAsJsonObject?.get("transaction_id")?.asString == tid) { + acceptToDeviceEvent = event + cancelLatch.countDown() + } + } + } + }) + + val aliceSession = cryptoTestData.firstSession + val aliceUserID = aliceSession.myUserId + val aliceDevice = aliceSession.crypto!!.myDevice.deviceId + + val aliceListener = object : VerificationManager.VerificationManagerListener { + override fun transactionCreated(tx: VerificationTransaction) {} + + override fun transactionUpdated(tx: VerificationTransaction) { + if ((tx as IncomingSASVerificationTransaction).uxState === IncomingSASVerificationTransaction.State.SHOW_ACCEPT) { + (tx as IncomingSASVerificationTransaction).performAccept(bobSession) + } + } + + override fun markedAsManuallyVerified(userId: String, deviceId: String) {} + } + aliceSession.crypto?.shortCodeVerificationManager?.addListener(aliceListener) + + + fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, protocols = protocols) + + mTestHelper.await(cancelLatch) + + + val acceptReq = JsonUtils.getBasicGson() + .fromJson(acceptToDeviceEvent!!.content, KeyVerificationAccept::class.java) + assertEquals("Request should be accepted with v1 protocol", SASVerificationTransaction.KEY_AGREEMENT_V1, acceptReq.keyAgreementProtocol) + + cryptoTestData.clear(context) + + } + + @Test fun test_key_agreement_macs_Must_include_hmac_sha256() { val context = InstrumentationRegistry.getContext() @@ -415,6 +472,7 @@ class SASTest { //check that agreement is valid assertTrue("Agreed Protocol should be Valid", accepted!!.isValid()) assertTrue("Agreed Protocol should be known by alice", startReq!!.keyAgreementProtocols!!.contains(accepted!!.keyAgreementProtocol)) + assertEquals("Agreed Protocol should be V2", "curve25519-hkdf-sha256", accepted!!.keyAgreementProtocol) assertTrue("Hash should be known by alice", startReq!!.hashes!!.contains(accepted!!.hash)) assertTrue("Hash should be known by alice", startReq!!.messageAuthenticationCodes!!.contains(accepted!!.messageAuthenticationCode)) From 90199518f7a7323511c8c611a916c5256875d77a Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 19 May 2020 18:45:25 +0200 Subject: [PATCH 3/5] code quality --- .../verification/IncomingSASVerificationTransaction.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt index 88837c8f1..bc1f0b5cd 100644 --- a/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt +++ b/matrix-sdk-crypto/src/main/java/org/matrix/androidsdk/crypto/verification/IncomingSASVerificationTransaction.kt @@ -212,7 +212,10 @@ class IncomingSASVerificationTransaction(transactionId: String, otherUserID: Str } KEY_AGREEMENT_V2 -> { // Adds the SAS public key, and separate by | - val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|$otherUserId|$otherDeviceId|$otherKey|${session.myUserId}|$myDeviceId|${getSAS().publicKey}|$transactionId" + val sasInfo = "MATRIX_KEY_VERIFICATION_SAS|" + + "$otherUserId|$otherDeviceId|$otherKey|" + + "${session.myUserId}|$myDeviceId|${getSAS().publicKey}|" + + transactionId return getSAS().generateShortCode(sasInfo, 6) } else -> { From cd04d9b287e3b2d56382208e4d5bab394af6d95c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2020 17:56:16 +0200 Subject: [PATCH 4/5] Fix crash on RoomAccountData The Exception should be caught, but it will explain why favourite rooms are vanishing. On some device, it crashed. --- CHANGES.rst | 2 +- .../matrix/androidsdk/data/RoomAccountData.java | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c25037f42..974668c54 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,7 +8,7 @@ Improvements: - Bugfix: - - + - Fix crash on RoomAccountData, on some devices API Change: - diff --git a/matrix-sdk/src/main/java/org/matrix/androidsdk/data/RoomAccountData.java b/matrix-sdk/src/main/java/org/matrix/androidsdk/data/RoomAccountData.java index 5bf4577d7..e9409ea66 100644 --- a/matrix-sdk/src/main/java/org/matrix/androidsdk/data/RoomAccountData.java +++ b/matrix-sdk/src/main/java/org/matrix/androidsdk/data/RoomAccountData.java @@ -18,10 +18,10 @@ package org.matrix.androidsdk.data; -import com.google.gson.JsonObject; - import androidx.annotation.Nullable; +import com.google.gson.JsonObject; + import org.matrix.androidsdk.core.JsonUtils; import org.matrix.androidsdk.rest.model.Event; import org.matrix.androidsdk.rest.model.TaggedEventInfo; @@ -80,7 +80,12 @@ public void handleEvent(Event event) { } // Store by default the content of all the provided events. - eventContentsMap.put(eventType, jsonObject); + if (jsonObject != null) { + eventContentsMap.put(eventType, jsonObject); + } else { + // Store an empty JsonObject + eventContentsMap.put(eventType, new JsonObject()); + } } /** @@ -177,10 +182,10 @@ public TaggedEventInfo hiddenEventInfo(String eventId) { /** * Provide the content of an handled event according to its type. - * @apiNote Use this method only when no dedicated method exists for the requested event type. * * @param eventType the type of the requested event. * @return the event content casted as JsonObject (null if no event has been handled with this type). + * @apiNote Use this method only when no dedicated method exists for the requested event type. */ @Nullable public JsonObject eventContent(String eventType) { @@ -189,16 +194,16 @@ public JsonObject eventContent(String eventType) { /** - * @deprecated use hasRoomTags() instead. * @return true if some tags have been defined for the room + * @deprecated use hasRoomTags() instead. */ public boolean hasTags() { return hasRoomTags(); } /** - * @deprecated use getRoomTagsKeys() instead. * @return the list of the keys used to defined the room tags, or null if there is no tag + * @deprecated use getRoomTagsKeys() instead. */ @Nullable public Set getKeys() { From 7e546cdb8c06d453bebb7a0d048fca0a920c3993 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 20 May 2020 22:42:56 +0200 Subject: [PATCH 5/5] Prepare release 0.9.35 --- CHANGES.rst | 20 +------------------- matrix-sdk/build.gradle | 2 +- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 86d23f1d8..27cd14680 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,30 +1,12 @@ -Changes to Matrix Android SDK in 0.9.35 (2020-XX-XX) +Changes to Matrix Android SDK in 0.9.35 (2020-05-20) ======================================================= -Features: - - - -Improvements: - - - Bugfix: - Fix crash on RoomAccountData, on some devices -API Change: - - - -Translations: - - - Others: - support new key agreement method for SAS (riotX/#1374) -Build: - - - -Test: - - - Changes to Matrix Android SDK in 0.9.34 (2020-05-13) ======================================================= diff --git a/matrix-sdk/build.gradle b/matrix-sdk/build.gradle index 21cb31049..2bd507e1e 100644 --- a/matrix-sdk/build.gradle +++ b/matrix-sdk/build.gradle @@ -28,7 +28,7 @@ android { minSdkVersion 16 targetSdkVersion 28 versionCode 935 - versionName "0.9.35-dev" + versionName "0.9.35" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Enable multi dex for test