From 95de49be304fe82c0a8bd675586787e47c32bdf0 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 19 Jul 2022 13:00:47 +0200 Subject: [PATCH] Added post quantum ZRTP stats + show ZRTP Post Quantum instead of ZRTP in call encryption settings if available + updated ZRTP SAS dialog with new layout --- CHANGELOG.md | 1 + app/src/main/assets/linphonerc_factory | 1 + .../viewmodels/CallSettingsViewModel.kt | 6 +- .../voip/data/CallStatisticsData.kt | 33 +++ .../activities/voip/data/StatItemData.kt | 29 +- .../voip/fragments/StatusFragment.kt | 8 +- .../drawable-xhdpi/security_post_quantum.png | Bin 0 -> 27796 bytes app/src/main/res/layout/dialog.xml | 56 ---- .../main/res/layout/voip_call_stat_cell.xml | 1 + .../main/res/layout/voip_call_stats_cell.xml | 18 ++ app/src/main/res/layout/voip_dialog.xml | 261 +++++++++++++----- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 9 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/strings.xml | 9 +- app/src/main/res/values/styles.xml | 6 +- 19 files changed, 302 insertions(+), 146 deletions(-) create mode 100644 app/src/main/res/drawable-xhdpi/security_post_quantum.png diff --git a/CHANGELOG.md b/CHANGELOG.md index e4aac2077..1396f056a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Group changes to describe their impact on the project, as follows: ## [4.7.0] - Unreleased ### Added +- Post Quantum encryption when using ZRTP - Conference creation with scheduling, video, different layouts, showing who is speaking and who is muted, etc... - Group calls directly from group chat rooms - Chat rooms can be individually muted (no notification when receiving a chat message) diff --git a/app/src/main/assets/linphonerc_factory b/app/src/main/assets/linphonerc_factory index c400cd45f..1c1e4c8e8 100644 --- a/app/src/main/assets/linphonerc_factory +++ b/app/src/main/assets/linphonerc_factory @@ -15,6 +15,7 @@ auto_net_state_mon=1 auto_answer_replacing_calls=1 ping_with_options=0 use_cpim=1 +zrtp_key_agreements_suites=MS_ZRTP_KEY_AGREEMENT_K255_KYB512 [sound] #remove this property for any application that is not Linphone public version itself diff --git a/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt b/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt index f37ec1b6c..7d99c7d7d 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/viewmodels/CallSettingsViewModel.kt @@ -290,7 +290,11 @@ class CallSettingsViewModel : GenericSettingsViewModel() { encryptionValues.add(MediaEncryption.SRTP.toInt()) } if (core.mediaEncryptionSupported(MediaEncryption.ZRTP)) { - labels.add(prefs.getString(R.string.call_settings_media_encryption_zrtp)) + if (core.postQuantumAvailable) { + labels.add(prefs.getString(R.string.call_settings_media_encryption_zrtp_post_quantum)) + } else { + labels.add(prefs.getString(R.string.call_settings_media_encryption_zrtp)) + } encryptionValues.add(MediaEncryption.ZRTP.toInt()) } if (core.mediaEncryptionSupported(MediaEncryption.DTLS)) { diff --git a/app/src/main/java/org/linphone/activities/voip/data/CallStatisticsData.kt b/app/src/main/java/org/linphone/activities/voip/data/CallStatisticsData.kt index 9cc205e76..6d4051df7 100644 --- a/app/src/main/java/org/linphone/activities/voip/data/CallStatisticsData.kt +++ b/app/src/main/java/org/linphone/activities/voip/data/CallStatisticsData.kt @@ -28,6 +28,8 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress val videoStats = MutableLiveData>() + val mediaEncryptionStats = MutableLiveData>() + val isVideoEnabled = MutableLiveData() private var enabled = false @@ -48,11 +50,16 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress val videoEnabled = call.currentParams.isVideoEnabled isVideoEnabled.value = videoEnabled + + updateMediaEncryptionStats() } fun enable() { enabled = true call.addListener(listener) + + // Needed for media encryption stats + updateMediaEncryptionStats() } fun disable() { @@ -65,8 +72,13 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress super.destroy() } + private fun updateMediaEncryptionStats() { + initCallStats() + } + private fun initCallStats() { val audioList = arrayListOf() + audioList.add(StatItemData(StatType.CAPTURE)) audioList.add(StatItemData(StatType.PLAYBACK)) audioList.add(StatItemData(StatType.PAYLOAD)) @@ -79,9 +91,26 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress audioList.add(StatItemData(StatType.SENDER_LOSS)) audioList.add(StatItemData(StatType.RECEIVER_LOSS)) audioList.add(StatItemData(StatType.JITTER)) + audioStats.value = audioList + val mediaEncryptionList = arrayListOf() + + mediaEncryptionList.add(StatItemData(StatType.MEDIA_ENCRYPTION)) + + // ZRTP stats are only available when authentication token isn't null ! + if (call.currentParams.mediaEncryption == MediaEncryption.ZRTP && call.authenticationToken != null) { + mediaEncryptionList.add(StatItemData(StatType.ZRTP_CIPHER_ALGO)) + mediaEncryptionList.add(StatItemData(StatType.ZRTP_KEY_AGREEMENT_ALGO)) + mediaEncryptionList.add(StatItemData(StatType.ZRTP_HASH_ALGO)) + mediaEncryptionList.add(StatItemData(StatType.ZRTP_AUTH_TAG_ALGO)) + mediaEncryptionList.add(StatItemData(StatType.ZRTP_AUTH_SAS_ALGO)) + } + + mediaEncryptionStats.value = mediaEncryptionList + val videoList = arrayListOf() + videoList.add(StatItemData(StatType.CAPTURE)) videoList.add(StatItemData(StatType.PLAYBACK)) videoList.add(StatItemData(StatType.PAYLOAD)) @@ -98,6 +127,7 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress videoList.add(StatItemData(StatType.RECEIVED_RESOLUTION)) videoList.add(StatItemData(StatType.SENT_FPS)) videoList.add(StatItemData(StatType.RECEIVED_FPS)) + videoStats.value = videoList } @@ -106,6 +136,9 @@ class CallStatisticsData(val call: Call) : GenericContactData(call.remoteAddress for (stat in audioStats.value.orEmpty()) { stat.update(call, stats) } + for (stat in mediaEncryptionStats.value.orEmpty()) { + stat.update(call, stats) + } } else if (stats.type == StreamType.Video) { for (stat in videoStats.value.orEmpty()) { stat.update(call, stats) diff --git a/app/src/main/java/org/linphone/activities/voip/data/StatItemData.kt b/app/src/main/java/org/linphone/activities/voip/data/StatItemData.kt index 92db22112..5057aefe0 100644 --- a/app/src/main/java/org/linphone/activities/voip/data/StatItemData.kt +++ b/app/src/main/java/org/linphone/activities/voip/data/StatItemData.kt @@ -23,6 +23,7 @@ import androidx.lifecycle.MutableLiveData import java.text.DecimalFormat import org.linphone.R import org.linphone.core.* +import org.linphone.utils.AppUtils enum class StatType(val nameResource: Int) { CAPTURE(R.string.call_stats_capture_filter), @@ -41,7 +42,13 @@ enum class StatType(val nameResource: Int) { RECEIVED_RESOLUTION(R.string.call_stats_video_resolution_received), SENT_FPS(R.string.call_stats_video_fps_sent), RECEIVED_FPS(R.string.call_stats_video_fps_received), - ESTIMATED_AVAILABLE_DOWNLOAD_BW(R.string.call_stats_estimated_download) + ESTIMATED_AVAILABLE_DOWNLOAD_BW(R.string.call_stats_estimated_download), + MEDIA_ENCRYPTION(R.string.call_stats_media_encryption), + ZRTP_CIPHER_ALGO(R.string.call_stats_zrtp_cipher_algo), + ZRTP_KEY_AGREEMENT_ALGO(R.string.call_stats_zrtp_key_agreement_algo), + ZRTP_HASH_ALGO(R.string.call_stats_zrtp_hash_algo), + ZRTP_AUTH_TAG_ALGO(R.string.call_stats_zrtp_auth_tag_algo), + ZRTP_AUTH_SAS_ALGO(R.string.call_stats_zrtp_sas_algo) } class StatItemData(val type: StatType) { @@ -75,6 +82,26 @@ class StatItemData(val type: StatType) { StatType.SENT_FPS -> "${call.currentParams.sentFramerate}" StatType.RECEIVED_FPS -> "${call.currentParams.receivedFramerate}" StatType.ESTIMATED_AVAILABLE_DOWNLOAD_BW -> "${stats.estimatedDownloadBandwidth} kbit/s" + StatType.MEDIA_ENCRYPTION -> { + when (call.currentParams.mediaEncryption) { + MediaEncryption.ZRTP -> { + if (stats.isZrtpKeyAgreementAlgoPostQuantum) { + AppUtils.getString(R.string.call_settings_media_encryption_zrtp_post_quantum) + } else { + AppUtils.getString(R.string.call_settings_media_encryption_zrtp) + } + } + MediaEncryption.DTLS -> AppUtils.getString(R.string.call_settings_media_encryption_dtls) + MediaEncryption.SRTP -> AppUtils.getString(R.string.call_settings_media_encryption_srtp) + MediaEncryption.None -> AppUtils.getString(R.string.call_settings_media_encryption_none) + else -> "Unexpected!" + } + } + StatType.ZRTP_CIPHER_ALGO -> stats.zrtpCipherAlgo + StatType.ZRTP_KEY_AGREEMENT_ALGO -> stats.zrtpKeyAgreementAlgo + StatType.ZRTP_HASH_ALGO -> stats.zrtpHashAlgo + StatType.ZRTP_AUTH_TAG_ALGO -> stats.zrtpAuthTagAlgo + StatType.ZRTP_AUTH_SAS_ALGO -> stats.zrtpSasAlgo } } } diff --git a/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt b/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt index 1f53b6eaa..e8ce89a73 100644 --- a/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt +++ b/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt @@ -112,9 +112,13 @@ class StatusFragment : GenericFragment() { viewModel.zrtpReadSas = toRead.uppercase(Locale.getDefault()) viewModel.zrtpListenSas = toListen.uppercase(Locale.getDefault()) viewModel.showIcon = true - viewModel.iconResource = R.drawable.security_2_indicator + viewModel.iconResource = if (call.audioStats?.isZrtpKeyAgreementAlgoPostQuantum == true) { + R.drawable.security_post_quantum + } else { + R.drawable.security_2_indicator + } - val dialog: Dialog = DialogUtils.getDialog(requireContext(), viewModel) + val dialog: Dialog = DialogUtils.getVoipDialog(requireContext(), viewModel) viewModel.showDeleteButton( { diff --git a/app/src/main/res/drawable-xhdpi/security_post_quantum.png b/app/src/main/res/drawable-xhdpi/security_post_quantum.png new file mode 100644 index 0000000000000000000000000000000000000000..9be1c4cdbb3b15c0df8404a3ad759ca2488dfac8 GIT binary patch literal 27796 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/dialog.xml b/app/src/main/res/layout/dialog.xml index 32b2f88ce..74aa030fd 100644 --- a/app/src/main/res/layout/dialog.xml +++ b/app/src/main/res/layout/dialog.xml @@ -43,62 +43,6 @@ android:gravity="center" android:text="@{viewModel.message, default=Message}"/> - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/voip_call_stats_cell.xml b/app/src/main/res/layout/voip_call_stats_cell.xml index 2a5a7952f..fab57ff2f 100644 --- a/app/src/main/res/layout/voip_call_stats_cell.xml +++ b/app/src/main/res/layout/voip_call_stats_cell.xml @@ -16,6 +16,24 @@ android:gravity="center" android:orientation="vertical"> + + + + - - - - - - - - + app:constraint_referenced_ids="dialog_icon, dialog_title, dialog_message" /> - + + + + + android:layout_margin="10dp" + android:gravity="center" + android:text="@{viewModel.title, default=Title}" + android:visibility="@{viewModel.showTitle ? View.VISIBLE : View.GONE}" + app:layout_constraintBottom_toTopOf="@id/dialog_message" + app:layout_constraintEnd_toEndOf="@id/background" + app:layout_constraintStart_toStartOf="@id/background" + app:layout_constraintTop_toBottomOf="@id/dialog_icon" /> + app:layout_constraintBottom_toTopOf="@id/dialog_zrtp_1" + app:layout_constraintEnd_toEndOf="@id/background" + app:layout_constraintStart_toStartOf="@id/background" + app:layout_constraintTop_toBottomOf="@id/dialog_title" /> + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 48348eb23..a8e8f55f6 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -414,7 +414,7 @@ Ninguno SRTP ZRTP - DTLS + DTLS-SRTP La encriptación de los medios es obligatoria Notificación de llamada superpuesta Se le pedirá que conceda el permiso de superposición diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index eb288f675..c762ebc3c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -277,7 +277,8 @@ Aucun SRTP ZRTP - DTLS + ZRTP Post Quantique + DTLS-SRTP Historique Afficher les détails du contact La qualité est très mauvaise @@ -737,4 +738,10 @@ Terminées Programmées Invitation à une réunion + Chiffrement du média : + Algorithme de chiffrement : + Algorithme d\'échange de clef : + Algorithme de hachage : + Algorithme d\'authentification : + Algorithme SAS : \ No newline at end of file diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 09c1a5207..4035ee46d 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -224,7 +224,7 @@ Média titkosítás SRTP ZRTP - DTLS + DTLS-SRTP Média titkosítása kötelező Hívás értesítés átfedése Átfedés megjelenítése az alkalmazáson kívül diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index ed664240d..ec7d975af 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -254,7 +254,7 @@ Nenhuma SRTP ZRTP - DTLS + DTLS-SRTP Melhore as interações com dispositivos bluetooth Requer algumas permissões extras Mostrar sobreposição fora do aplicativo diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 441ad7c02..aa26b2fad 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -256,7 +256,7 @@ Настройки уведомлений Android SRTP ZRTP - DTLS + DTLS-SRTP Автоматически начинать запись разговоров URL сервера обмена Не изменяйте, если вы не знаете, что делаете! diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 8fbcd29e7..91965d3e8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -271,7 +271,7 @@ SRTP ZRTP - DTLS + DTLS-SRTP 系統將請您授權「顯示在其他應用程式上層」權限 傳送帶内撥號音(RFC 2833) 立即開始通話 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f5386e049..38ce5719e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -360,6 +360,12 @@ Decoder: Player filter: Capture filter: + Media encryption: + Cipher algorithm: + Key agreement algorithm: + Hash algorithm: + Authentication algorithm: + SAS algorithm: Welcome @@ -497,7 +503,8 @@ None SRTP ZRTP - DTLS + Post Quantum ZRTP + DTLS-SRTP Media encryption mandatory Improve interactions with bluetooth devices Requires some extra permissions diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7d008fbbf..83d061e12 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -341,7 +341,7 @@