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 000000000..9be1c4cdb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/security_post_quantum.png differ 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 @@