Move VFS Activation at earlier stage
This commit is contained in:
parent
9ccab891ab
commit
571349953b
3 changed files with 102 additions and 102 deletions
|
@ -44,6 +44,10 @@ class LinphoneApplication : Application() {
|
||||||
corePreferences = CorePreferences(context)
|
corePreferences = CorePreferences(context)
|
||||||
corePreferences.copyAssetsFromPackage()
|
corePreferences.copyAssetsFromPackage()
|
||||||
|
|
||||||
|
if (corePreferences.vfsEnabled) {
|
||||||
|
CoreContext.activateVFS()
|
||||||
|
}
|
||||||
|
|
||||||
val config = Factory.instance().createConfigWithFactory(corePreferences.configPath, corePreferences.factoryConfigPath)
|
val config = Factory.instance().createConfigWithFactory(corePreferences.configPath, corePreferences.factoryConfigPath)
|
||||||
corePreferences.config = config
|
corePreferences.config = config
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.activities.main.settings.SettingListenerStub
|
import org.linphone.activities.main.settings.SettingListenerStub
|
||||||
|
import org.linphone.core.CoreContext
|
||||||
import org.linphone.core.Factory
|
import org.linphone.core.Factory
|
||||||
import org.linphone.mediastream.Version
|
import org.linphone.mediastream.Version
|
||||||
import org.linphone.utils.AppUtils
|
import org.linphone.utils.AppUtils
|
||||||
|
@ -107,7 +108,7 @@ class AdvancedSettingsViewModel : GenericSettingsViewModel() {
|
||||||
val vfsListener = object : SettingListenerStub() {
|
val vfsListener = object : SettingListenerStub() {
|
||||||
override fun onBoolValueChanged(newValue: Boolean) {
|
override fun onBoolValueChanged(newValue: Boolean) {
|
||||||
prefs.vfsEnabled = newValue
|
prefs.vfsEnabled = newValue
|
||||||
if (newValue) coreContext.activateVFS()
|
if (newValue) CoreContext.activateVFS()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val vfs = MutableLiveData<Boolean>()
|
val vfs = MutableLiveData<Boolean>()
|
||||||
|
|
|
@ -291,9 +291,6 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
Log.i("[Context] Crashlytics enabled, register logging service listener")
|
Log.i("[Context] Crashlytics enabled, register logging service listener")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (corePreferences.vfsEnabled) {
|
|
||||||
activateVFS()
|
|
||||||
}
|
|
||||||
core = Factory.instance().createCoreWithConfig(coreConfig, context)
|
core = Factory.instance().createCoreWithConfig(coreConfig, context)
|
||||||
|
|
||||||
stopped = false
|
stopped = false
|
||||||
|
@ -685,111 +682,109 @@ class CoreContext(val context: Context, coreConfig: Config) {
|
||||||
private const val LINPHONE_VFS_ENCRYPTION_AES256GCM128_SHA256 = 2
|
private const val LINPHONE_VFS_ENCRYPTION_AES256GCM128_SHA256 = 2
|
||||||
private const val VFS_IV = "vfsiv"
|
private const val VFS_IV = "vfsiv"
|
||||||
private const val VFS_KEY = "vfskey"
|
private const val VFS_KEY = "vfskey"
|
||||||
}
|
@Throws(java.lang.Exception::class)
|
||||||
|
private fun generateSecretKey() {
|
||||||
@Throws(java.lang.Exception::class)
|
val keyGenerator =
|
||||||
private fun generateSecretKey() {
|
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE)
|
||||||
val keyGenerator =
|
keyGenerator.init(
|
||||||
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE)
|
KeyGenParameterSpec.Builder(
|
||||||
keyGenerator.init(
|
ALIAS,
|
||||||
KeyGenParameterSpec.Builder(
|
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
|
||||||
ALIAS,
|
)
|
||||||
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
|
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
||||||
|
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
keyGenerator.generateKey()
|
||||||
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
keyGenerator.generateKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
private fun getSecretKey(): SecretKey? {
|
|
||||||
val ks = KeyStore.getInstance(ANDROID_KEY_STORE)
|
|
||||||
ks.load(null)
|
|
||||||
val entry = ks.getEntry(ALIAS, null) as KeyStore.SecretKeyEntry
|
|
||||||
return entry.secretKey
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
fun generateToken(): String? {
|
|
||||||
return sha512(UUID.randomUUID().toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
private fun encryptData(textToEncrypt: String): Pair<ByteArray, ByteArray> {
|
|
||||||
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
|
|
||||||
val iv = cipher.iv
|
|
||||||
return Pair<ByteArray, ByteArray>(
|
|
||||||
iv,
|
|
||||||
cipher.doFinal(textToEncrypt.toByteArray(StandardCharsets.UTF_8))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
private fun decryptData(encrypted: String?, encryptionIv: ByteArray): String {
|
|
||||||
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
||||||
val spec = GCMParameterSpec(128, encryptionIv)
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), spec)
|
|
||||||
val encryptedData = Base64.decode(encrypted, Base64.DEFAULT)
|
|
||||||
return String(cipher.doFinal(encryptedData), StandardCharsets.UTF_8)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
fun encryptToken(string_to_encrypt: String): Pair<String?, String?> {
|
|
||||||
val encryptedData = encryptData(string_to_encrypt)
|
|
||||||
return Pair<String?, String?>(
|
|
||||||
Base64.encodeToString(encryptedData.first, Base64.DEFAULT),
|
|
||||||
Base64.encodeToString(encryptedData.second, Base64.DEFAULT)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
|
||||||
fun sha512(input: String): String {
|
|
||||||
val md = MessageDigest.getInstance("SHA-512")
|
|
||||||
val messageDigest = md.digest(input.toByteArray())
|
|
||||||
val no = BigInteger(1, messageDigest)
|
|
||||||
var hashtext = no.toString(16)
|
|
||||||
while (hashtext.length < 32) {
|
|
||||||
hashtext = "0$hashtext"
|
|
||||||
}
|
}
|
||||||
return hashtext
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(java.lang.Exception::class)
|
@Throws(java.lang.Exception::class)
|
||||||
fun getVfsKey(sharedPreferences: SharedPreferences): String {
|
private fun getSecretKey(): SecretKey? {
|
||||||
val keyStore = KeyStore.getInstance(ANDROID_KEY_STORE)
|
val ks = KeyStore.getInstance(ANDROID_KEY_STORE)
|
||||||
keyStore.load(null)
|
ks.load(null)
|
||||||
return decryptData(
|
val entry = ks.getEntry(ALIAS, null) as KeyStore.SecretKeyEntry
|
||||||
sharedPreferences.getString(VFS_KEY, null),
|
return entry.secretKey
|
||||||
Base64.decode(sharedPreferences.getString(VFS_IV, null), Base64.DEFAULT)
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun activateVFS() {
|
@Throws(java.lang.Exception::class)
|
||||||
try {
|
fun generateToken(): String? {
|
||||||
Log.i("[Context] Activating VFS")
|
return sha512(UUID.randomUUID().toString())
|
||||||
|
}
|
||||||
|
|
||||||
if (corePreferences.encryptedSharedPreferences.getString(VFS_IV, null) == null) {
|
@Throws(java.lang.Exception::class)
|
||||||
generateSecretKey()
|
private fun encryptData(textToEncrypt: String): Pair<ByteArray, ByteArray> {
|
||||||
generateToken()?.let { encryptToken(it) }?.let { data ->
|
val cipher = Cipher.getInstance(TRANSFORMATION)
|
||||||
corePreferences.encryptedSharedPreferences
|
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
|
||||||
.edit()
|
val iv = cipher.iv
|
||||||
.putString(VFS_IV, data.first)
|
return Pair<ByteArray, ByteArray>(
|
||||||
.putString(VFS_KEY, data.second)
|
iv,
|
||||||
.commit()
|
cipher.doFinal(textToEncrypt.toByteArray(StandardCharsets.UTF_8))
|
||||||
}
|
|
||||||
}
|
|
||||||
Factory.instance().setVfsEncryption(
|
|
||||||
LINPHONE_VFS_ENCRYPTION_AES256GCM128_SHA256,
|
|
||||||
getVfsKey(corePreferences.encryptedSharedPreferences).toByteArray().copyOfRange(0, 32),
|
|
||||||
32
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Log.i("[Context] VFS activated.")
|
@Throws(java.lang.Exception::class)
|
||||||
} catch (e: Exception) {
|
private fun decryptData(encrypted: String?, encryptionIv: ByteArray): String {
|
||||||
Log.f("[Context] Unable to activate VFS encryption: $e")
|
val cipher = Cipher.getInstance(TRANSFORMATION)
|
||||||
|
val spec = GCMParameterSpec(128, encryptionIv)
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), spec)
|
||||||
|
val encryptedData = Base64.decode(encrypted, Base64.DEFAULT)
|
||||||
|
return String(cipher.doFinal(encryptedData), StandardCharsets.UTF_8)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(java.lang.Exception::class)
|
||||||
|
fun encryptToken(string_to_encrypt: String): Pair<String?, String?> {
|
||||||
|
val encryptedData = encryptData(string_to_encrypt)
|
||||||
|
return Pair<String?, String?>(
|
||||||
|
Base64.encodeToString(encryptedData.first, Base64.DEFAULT),
|
||||||
|
Base64.encodeToString(encryptedData.second, Base64.DEFAULT)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(java.lang.Exception::class)
|
||||||
|
fun sha512(input: String): String {
|
||||||
|
val md = MessageDigest.getInstance("SHA-512")
|
||||||
|
val messageDigest = md.digest(input.toByteArray())
|
||||||
|
val no = BigInteger(1, messageDigest)
|
||||||
|
var hashtext = no.toString(16)
|
||||||
|
while (hashtext.length < 32) {
|
||||||
|
hashtext = "0$hashtext"
|
||||||
|
}
|
||||||
|
return hashtext
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(java.lang.Exception::class)
|
||||||
|
fun getVfsKey(sharedPreferences: SharedPreferences): String {
|
||||||
|
val keyStore = KeyStore.getInstance(ANDROID_KEY_STORE)
|
||||||
|
keyStore.load(null)
|
||||||
|
return decryptData(
|
||||||
|
sharedPreferences.getString(VFS_KEY, null),
|
||||||
|
Base64.decode(sharedPreferences.getString(VFS_IV, null), Base64.DEFAULT)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fun activateVFS() {
|
||||||
|
try {
|
||||||
|
Log.i("[Context] Activating VFS")
|
||||||
|
|
||||||
|
if (corePreferences.encryptedSharedPreferences.getString(VFS_IV, null) == null) {
|
||||||
|
generateSecretKey()
|
||||||
|
generateToken()?.let { encryptToken(it) }?.let { data ->
|
||||||
|
corePreferences.encryptedSharedPreferences
|
||||||
|
.edit()
|
||||||
|
.putString(VFS_IV, data.first)
|
||||||
|
.putString(VFS_KEY, data.second)
|
||||||
|
.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Factory.instance().setVfsEncryption(
|
||||||
|
LINPHONE_VFS_ENCRYPTION_AES256GCM128_SHA256,
|
||||||
|
getVfsKey(corePreferences.encryptedSharedPreferences).toByteArray().copyOfRange(0, 32),
|
||||||
|
32
|
||||||
|
)
|
||||||
|
|
||||||
|
Log.i("[Context] VFS activated.")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.f("[Context] Unable to activate VFS encryption: $e")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue