forked from hardcoresushi/DroidFS
Allow changing password of CryFS volumes
This commit is contained in:
parent
1a21a43f05
commit
d1ca164934
@ -1 +1 @@
|
||||
Subproject commit cf822d6a5bb0bb3492ec350d2648f14c859f846f
|
||||
Subproject commit c5be03ad3abea3aef5b0fcc5aa3af8cba2befdd1
|
@ -9,7 +9,11 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding
|
||||
import sushi.hardcore.droidfs.filesystems.CryfsVolume
|
||||
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
|
||||
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.util.ObjRef
|
||||
import sushi.hardcore.droidfs.util.WidgetUtil
|
||||
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
||||
import java.util.*
|
||||
|
||||
@ -66,14 +70,12 @@ class ChangePasswordActivity: BaseActivity() {
|
||||
}
|
||||
|
||||
private fun changeVolumePassword() {
|
||||
val newPassword = CharArray(binding.editNewPassword.text.length)
|
||||
binding.editNewPassword.text.getChars(0, newPassword.size, newPassword, 0)
|
||||
val newPasswordConfirm = CharArray(binding.editPasswordConfirm.text.length)
|
||||
binding.editPasswordConfirm.text.getChars(0, newPasswordConfirm.size, newPasswordConfirm, 0)
|
||||
val newPassword = WidgetUtil.encodeEditTextContent(binding.editNewPassword)
|
||||
val newPasswordConfirm = WidgetUtil.encodeEditTextContent(binding.editPasswordConfirm)
|
||||
@SuppressLint("NewApi")
|
||||
if (!newPassword.contentEquals(newPasswordConfirm)) {
|
||||
Toast.makeText(this, R.string.passwords_mismatch, Toast.LENGTH_SHORT).show()
|
||||
Arrays.fill(newPassword, 0.toChar())
|
||||
Arrays.fill(newPassword, 0)
|
||||
} else {
|
||||
var changeWithCurrentPassword = true
|
||||
volume.encryptedHash?.let { encryptedHash ->
|
||||
@ -91,7 +93,7 @@ class ChangePasswordActivity: BaseActivity() {
|
||||
}
|
||||
override fun onPasswordHashSaved() {}
|
||||
override fun onFailed(pending: Boolean) {
|
||||
Arrays.fill(newPassword, 0.toChar())
|
||||
Arrays.fill(newPassword, 0)
|
||||
}
|
||||
}
|
||||
it.loadPasswordHash(volume.name, encryptedHash, iv)
|
||||
@ -102,30 +104,48 @@ class ChangePasswordActivity: BaseActivity() {
|
||||
changeVolumePassword(newPassword)
|
||||
}
|
||||
}
|
||||
Arrays.fill(newPasswordConfirm, 0.toChar())
|
||||
Arrays.fill(newPasswordConfirm, 0)
|
||||
}
|
||||
|
||||
private fun changeVolumePassword(newPassword: CharArray, givenHash: ByteArray? = null) {
|
||||
var returnedHash: ByteArray? = null
|
||||
if (binding.checkboxSavePassword.isChecked) {
|
||||
returnedHash = ByteArray(GocryptfsVolume.KeyLen)
|
||||
private fun changeVolumePassword(newPassword: ByteArray, givenHash: ByteArray? = null) {
|
||||
val returnedHash: ObjRef<ByteArray?>? = if (binding.checkboxSavePassword.isChecked) {
|
||||
ObjRef(null)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
var currentPassword: CharArray? = null
|
||||
if (givenHash == null) {
|
||||
currentPassword = CharArray(binding.editCurrentPassword.text.length)
|
||||
binding.editCurrentPassword.text.getChars(0, currentPassword.size, currentPassword, 0)
|
||||
val currentPassword = if (givenHash == null) {
|
||||
WidgetUtil.encodeEditTextContent(binding.editCurrentPassword)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
object : LoadingTask<Boolean>(this, themeValue, R.string.loading_msg_change_password) {
|
||||
override suspend fun doTask(): Boolean {
|
||||
val success = GocryptfsVolume.changePassword(volume.getFullPath(filesDir.path), currentPassword, givenHash, newPassword, returnedHash)
|
||||
val success = if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE) {
|
||||
GocryptfsVolume.changePassword(
|
||||
volume.getFullPath(filesDir.path),
|
||||
currentPassword,
|
||||
givenHash,
|
||||
newPassword,
|
||||
returnedHash?.apply { value = ByteArray(GocryptfsVolume.KeyLen) }?.value
|
||||
)
|
||||
} else {
|
||||
CryfsVolume.changePassword(
|
||||
volume.getFullPath(filesDir.path),
|
||||
filesDir.path,
|
||||
currentPassword,
|
||||
givenHash,
|
||||
newPassword,
|
||||
returnedHash
|
||||
)
|
||||
}
|
||||
if (success) {
|
||||
if (volumeDatabase.isHashSaved(volume.name)) {
|
||||
volumeDatabase.removeHash(volume)
|
||||
}
|
||||
}
|
||||
if (currentPassword != null)
|
||||
Arrays.fill(currentPassword, 0.toChar())
|
||||
Arrays.fill(newPassword, 0.toChar())
|
||||
Arrays.fill(currentPassword, 0)
|
||||
Arrays.fill(newPassword, 0)
|
||||
if (givenHash != null)
|
||||
Arrays.fill(givenHash, 0)
|
||||
return success
|
||||
@ -138,21 +158,21 @@ class ChangePasswordActivity: BaseActivity() {
|
||||
it.listener = object : FingerprintProtector.Listener {
|
||||
override fun onHashStorageReset() {
|
||||
// retry
|
||||
it.savePasswordHash(volume, returnedHash)
|
||||
it.savePasswordHash(volume, returnedHash.value!!)
|
||||
}
|
||||
override fun onPasswordHashDecrypted(hash: ByteArray) {}
|
||||
override fun onPasswordHashSaved() {
|
||||
Arrays.fill(returnedHash, 0)
|
||||
Arrays.fill(returnedHash.value!!, 0)
|
||||
finish()
|
||||
}
|
||||
override fun onFailed(pending: Boolean) {
|
||||
if (!pending) {
|
||||
Arrays.fill(returnedHash, 0)
|
||||
Arrays.fill(returnedHash.value!!, 0)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
it.savePasswordHash(volume, returnedHash)
|
||||
it.savePasswordHash(volume, returnedHash.value!!)
|
||||
}
|
||||
} else {
|
||||
finish()
|
||||
|
@ -342,11 +342,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
|
||||
val onlyOneAndWriteable =
|
||||
onlyOneSelected &&
|
||||
volumeAdapter.volumes[volumeAdapter.selectedItems.first()].canWrite(filesDir.path)
|
||||
menu.findItem(R.id.change_password).isVisible =
|
||||
onlyOneAndWriteable &&
|
||||
// Only gocryptfs volumes support password change
|
||||
!BuildConfig.GOCRYPTFS_DISABLED &&
|
||||
volumeAdapter.volumes[volumeAdapter.selectedItems.first()].type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE
|
||||
menu.findItem(R.id.change_password).isVisible = onlyOneAndWriteable
|
||||
menu.findItem(R.id.remove_default_open).isVisible =
|
||||
onlyOneSelected &&
|
||||
volumeAdapter.volumes[volumeAdapter.selectedItems.first()].name == defaultVolumeName
|
||||
|
@ -23,6 +23,14 @@ class CryfsVolume(private val fusePtr: Long): EncryptedVolume() {
|
||||
createBaseDir: Boolean,
|
||||
cipher: String?
|
||||
): Long
|
||||
private external fun nativeChangeEncryptionKey(
|
||||
baseDir: String,
|
||||
localStateDir: String,
|
||||
currentPassword: ByteArray?,
|
||||
givenHash: ByteArray?,
|
||||
newPassword: ByteArray,
|
||||
returnedHash: ObjRef<ByteArray?>?
|
||||
): Boolean
|
||||
private external fun nativeCreate(fusePtr: Long, path: String, mode: Int): Long
|
||||
private external fun nativeOpen(fusePtr: Long, path: String, flags: Int): Long
|
||||
private external fun nativeRead(fusePtr: Long, fileHandle: Long, buffer: ByteArray, offset: Long): Int
|
||||
@ -66,6 +74,15 @@ class CryfsVolume(private val fusePtr: Long): EncryptedVolume() {
|
||||
fun init(baseDir: String, localStateDir: String, password: ByteArray?, givenHash: ByteArray?, returnedHash: ObjRef<ByteArray?>?): CryfsVolume? {
|
||||
return init(baseDir, localStateDir, password, givenHash, returnedHash, false, null)
|
||||
}
|
||||
|
||||
fun changePassword(
|
||||
baseDir: String, filesDir: String, currentPassword: ByteArray?,
|
||||
givenHash: ByteArray?,
|
||||
newPassword: ByteArray,
|
||||
returnedHash: ObjRef<ByteArray?>?
|
||||
): Boolean {
|
||||
return nativeChangeEncryptionKey(baseDir, getLocalStateDir(filesDir), currentPassword, givenHash, newPassword, returnedHash)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(parcel: Parcel) : this(parcel.readLong())
|
||||
|
@ -25,7 +25,13 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
|
||||
const val CONFIG_FILE_NAME = "gocryptfs.conf"
|
||||
external fun createVolume(root_cipher_dir: String, password: ByteArray, plainTextNames: Boolean, xchacha: Int, logN: Int, creator: String, returnedHash: ByteArray?): Boolean
|
||||
private external fun nativeInit(root_cipher_dir: String, password: ByteArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int
|
||||
external fun changePassword(root_cipher_dir: String, old_password: CharArray?, givenHash: ByteArray?, new_password: CharArray, returnedHash: ByteArray?): Boolean
|
||||
external fun changePassword(
|
||||
root_cipher_dir: String,
|
||||
currentPassword: ByteArray?,
|
||||
givenHash: ByteArray?,
|
||||
newPassword: ByteArray,
|
||||
returnedHash: ByteArray?
|
||||
): Boolean
|
||||
|
||||
fun init(root_cipher_dir: String, password: ByteArray?, givenHash: ByteArray?, returnedHash: ByteArray?): GocryptfsVolume? {
|
||||
val sessionId = nativeInit(root_cipher_dir, password, givenHash, returnedHash)
|
||||
|
@ -12,6 +12,14 @@ Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeInit(JN
|
||||
return cryfs_init(env, base_dir, jlocalStateDir, password, givenHash, returnedHash, createBaseDir, cipher);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeChangeEncryptionKey(
|
||||
JNIEnv *env, jobject thiz, jstring base_dir, jstring local_state_dir,
|
||||
jbyteArray current_password, jbyteArray given_hash, jbyteArray new_password,
|
||||
jobject returned_hash) {
|
||||
return cryfs_change_encryption_key(env, base_dir, local_state_dir, current_password, given_hash, new_password, returned_hash);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sushi_hardcore_droidfs_filesystems_CryfsVolume_00024Companion_nativeCreate(JNIEnv *env, jobject thiz,
|
||||
jlong fuse_ptr, jstring path,
|
||||
|
Loading…
Reference in New Issue
Block a user