Modular build

This commit is contained in:
Matéo Duparc 2022-06-24 19:54:49 +02:00
parent 53f4e3507b
commit 43a3f72935
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
18 changed files with 122 additions and 98 deletions

View File

@ -1,6 +1,11 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
ext {
enableCryFS = true
enableGocryptfs = true
}
android { android {
compileSdkVersion 31 compileSdkVersion 31
buildToolsVersion "31" buildToolsVersion "31"
@ -21,6 +26,16 @@ android {
ndk { ndk {
abiFilters "x86", "x86_64", "armeabi-v7a", "arm64-v8a" abiFilters "x86", "x86_64", "armeabi-v7a", "arm64-v8a"
} }
externalNativeBuild.cmake {
targets "mux"
if (project.ext.enableGocryptfs) {
targets += "gocryptfs_jni"
}
if (project.ext.enableCryFS) {
targets += "cryfs_jni"
}
}
} }
if (!file("fdroid").exists()) { if (!file("fdroid").exists()) {
@ -34,6 +49,8 @@ android {
applicationVariants.all { variant -> applicationVariants.all { variant ->
variant.resValue "string", "versionName", variant.versionName variant.resValue "string", "versionName", variant.versionName
buildConfigField "boolean", "CRYFS_ENABLED", "${project.ext.enableCryFS}"
buildConfigField "boolean", "GOCRYPTFS_ENABLED", "${project.ext.enableGocryptfs}"
} }
buildFeatures { buildFeatures {

@ -1 +1 @@
Subproject commit 6cd6d9ef5d2f3f41581fbac5d3eb413364714dcf Subproject commit fb593c468c62c2f92b0420e80e1f77c001dd3a24

View File

@ -9,6 +9,7 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding import sushi.hardcore.droidfs.databinding.ActivityChangePasswordBinding
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.util.* import java.util.*

View File

@ -11,6 +11,7 @@ object ConstValues {
val FAKE_URI: Uri = Uri.parse("fakeuri://droidfs") val FAKE_URI: Uri = Uri.parse("fakeuri://droidfs")
const val MAX_KERNEL_WRITE = 128*1024 const val MAX_KERNEL_WRITE = 128*1024
const val WIPE_PASSES = 2 const val WIPE_PASSES = 2
const val IO_BUFF_SIZE = 16384
const val SLIDESHOW_DELAY: Long = 4000 const val SLIDESHOW_DELAY: Long = 4000
const val DEFAULT_THEME_VALUE = "dark_green" const val DEFAULT_THEME_VALUE = "dark_green"
const val THUMBNAIL_MAX_SIZE_KEY = "thumbnail_max_size" const val THUMBNAIL_MAX_SIZE_KEY = "thumbnail_max_size"

View File

@ -31,13 +31,12 @@ import sushi.hardcore.droidfs.explorers.ExplorerActivityDrop
import sushi.hardcore.droidfs.explorers.ExplorerActivityPick import sushi.hardcore.droidfs.explorers.ExplorerActivityPick
import sushi.hardcore.droidfs.file_operations.FileOperationService import sushi.hardcore.droidfs.file_operations.FileOperationService
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.WidgetUtil import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog import sushi.hardcore.droidfs.widgets.EditTextDialog
import java.io.File import java.io.File
import java.nio.CharBuffer
import java.nio.charset.StandardCharsets
import java.util.* import java.util.*
class MainActivity : BaseActivity(), VolumeAdapter.Listener { class MainActivity : BaseActivity(), VolumeAdapter.Listener {
@ -346,6 +345,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
menu.findItem(R.id.change_password).isVisible = menu.findItem(R.id.change_password).isVisible =
onlyOneAndWriteable && onlyOneAndWriteable &&
// Only gocryptfs volumes support password change // Only gocryptfs volumes support password change
BuildConfig.GOCRYPTFS_ENABLED &&
volumeAdapter.volumes[volumeAdapter.selectedItems.first()].type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE volumeAdapter.volumes[volumeAdapter.selectedItems.first()].type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE
menu.findItem(R.id.remove_default_open).isVisible = menu.findItem(R.id.remove_default_open).isVisible =
onlyOneSelected && onlyOneSelected &&
@ -461,6 +461,13 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
@SuppressLint("NewApi") // fingerprintProtector is non-null only when SDK_INT >= 23 @SuppressLint("NewApi") // fingerprintProtector is non-null only when SDK_INT >= 23
private fun openVolume(volume: SavedVolume, position: Int) { private fun openVolume(volume: SavedVolume, position: Int) {
if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE && !BuildConfig.GOCRYPTFS_ENABLED) {
Toast.makeText(this, R.string.gocryptfs_disabled, Toast.LENGTH_SHORT).show()
return
} else if (volume.type == EncryptedVolume.CRYFS_VOLUME_TYPE && !BuildConfig.CRYFS_ENABLED) {
Toast.makeText(this, R.string.cryfs_disabled, Toast.LENGTH_SHORT).show()
return
}
var askForPassword = true var askForPassword = true
fingerprintProtector?.let { fingerprintProtector -> fingerprintProtector?.let { fingerprintProtector ->
volume.encryptedHash?.let { encryptedHash -> volume.encryptedHash?.let { encryptedHash ->
@ -646,11 +653,8 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
if (pickMode && !usfKeepOpen) { if (pickMode && !usfKeepOpen) {
finish() finish()
if (shouldCloseVolume) { if (shouldCloseVolume) {
val sessionID = intent.getIntExtra("sessionID", -1) intent.getParcelableExtra<EncryptedVolume>("volume")?.close()
if (sessionID != -1) { RestrictedFileProvider.wipeAll(this)
GocryptfsVolume(sessionID).close()
RestrictedFileProvider.wipeAll(this)
}
} }
} }
} }

View File

@ -17,10 +17,12 @@ import sushi.hardcore.droidfs.*
import sushi.hardcore.droidfs.databinding.FragmentCreateVolumeBinding import sushi.hardcore.droidfs.databinding.FragmentCreateVolumeBinding
import sushi.hardcore.droidfs.filesystems.CryfsVolume import sushi.hardcore.droidfs.filesystems.CryfsVolume
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
import sushi.hardcore.droidfs.util.WidgetUtil import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.File import java.io.File
import java.util.* import java.util.*
import kotlin.collections.ArrayList
class CreateVolumeFragment: Fragment() { class CreateVolumeFragment: Fragment() {
companion object { companion object {
@ -51,6 +53,7 @@ class CreateVolumeFragment: Fragment() {
private lateinit var binding: FragmentCreateVolumeBinding private lateinit var binding: FragmentCreateVolumeBinding
private var themeValue = ConstValues.DEFAULT_THEME_VALUE private var themeValue = ConstValues.DEFAULT_THEME_VALUE
private val volumeTypes = ArrayList<String>(2)
private lateinit var volumePath: String private lateinit var volumePath: String
private var isHiddenVolume: Boolean = false private var isHiddenVolume: Boolean = false
private var usfFingerprint: Boolean = false private var usfFingerprint: Boolean = false
@ -82,10 +85,16 @@ class CreateVolumeFragment: Fragment() {
if (!usfFingerprint || fingerprintProtector == null) { if (!usfFingerprint || fingerprintProtector == null) {
binding.checkboxSavePassword.visibility = View.GONE binding.checkboxSavePassword.visibility = View.GONE
} }
if (BuildConfig.GOCRYPTFS_ENABLED) {
volumeTypes.add(resources.getString(R.string.gocryptfs))
}
if (BuildConfig.CRYFS_ENABLED) {
volumeTypes.add(resources.getString(R.string.cryfs))
}
binding.spinnerVolumeType.adapter = ArrayAdapter( binding.spinnerVolumeType.adapter = ArrayAdapter(
requireContext(), requireContext(),
android.R.layout.simple_spinner_item, android.R.layout.simple_spinner_item,
resources.getStringArray(R.array.volume_types) volumeTypes
).apply { ).apply {
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
} }
@ -98,8 +107,10 @@ class CreateVolumeFragment: Fragment() {
} }
binding.spinnerVolumeType.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { binding.spinnerVolumeType.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val ciphersArray = if (position == 0) { // Gocryptfs val ciphersArray = if (volumeTypes[position] == resources.getString(R.string.gocryptfs)) {
binding.checkboxSavePassword.visibility = View.VISIBLE if (usfFingerprint && fingerprintProtector != null) {
binding.checkboxSavePassword.visibility = View.VISIBLE
}
R.array.gocryptfs_encryption_ciphers R.array.gocryptfs_encryption_ciphers
} else { } else {
binding.checkboxSavePassword.visibility = View.GONE binding.checkboxSavePassword.visibility = View.GONE
@ -164,7 +175,7 @@ class CreateVolumeFragment: Fragment() {
val volumeFile = File(volumePath) val volumeFile = File(volumePath)
if (!volumeFile.exists()) if (!volumeFile.exists())
volumeFile.mkdirs() volumeFile.mkdirs()
val volume = if (binding.spinnerVolumeType.selectedItem == 0) { // Gocryptfs val volume = if (volumeTypes[binding.spinnerVolumeType.selectedItemPosition] == resources.getString(R.string.gocryptfs)) {
val xchacha = when (binding.spinnerCipher.selectedItemPosition) { val xchacha = when (binding.spinnerCipher.selectedItemPosition) {
0 -> 0 0 -> 0
1 -> 1 1 -> 1

View File

@ -32,7 +32,6 @@ import sushi.hardcore.droidfs.ConstValues.isImage
import sushi.hardcore.droidfs.ConstValues.isPDF import sushi.hardcore.droidfs.ConstValues.isPDF
import sushi.hardcore.droidfs.ConstValues.isText import sushi.hardcore.droidfs.ConstValues.isText
import sushi.hardcore.droidfs.ConstValues.isVideo import sushi.hardcore.droidfs.ConstValues.isVideo
import sushi.hardcore.droidfs.GocryptfsVolume
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.adapters.ExplorerElementAdapter import sushi.hardcore.droidfs.adapters.ExplorerElementAdapter
import sushi.hardcore.droidfs.adapters.OpenAsDialogAdapter import sushi.hardcore.droidfs.adapters.OpenAsDialogAdapter

View File

@ -3,7 +3,6 @@ package sushi.hardcore.droidfs.explorers
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
@ -12,7 +11,6 @@ import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import sushi.hardcore.droidfs.CameraActivity import sushi.hardcore.droidfs.CameraActivity
import sushi.hardcore.droidfs.GocryptfsVolume
import sushi.hardcore.droidfs.MainActivity import sushi.hardcore.droidfs.MainActivity
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.adapters.IconTextDialogAdapter import sushi.hardcore.droidfs.adapters.IconTextDialogAdapter
@ -24,7 +22,6 @@ import sushi.hardcore.droidfs.filesystems.Stat
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.EditTextDialog import sushi.hardcore.droidfs.widgets.EditTextDialog
import java.io.File
class ExplorerActivity : BaseExplorerActivity() { class ExplorerActivity : BaseExplorerActivity() {
companion object { companion object {

View File

@ -2,14 +2,11 @@ package sushi.hardcore.droidfs.explorers
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.GocryptfsVolume
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import java.util.*
class ExplorerActivityPick : BaseExplorerActivity() { class ExplorerActivityPick : BaseExplorerActivity() {
private var resultIntent = Intent() private var resultIntent = Intent()

View File

@ -14,7 +14,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import kotlinx.coroutines.* import kotlinx.coroutines.*
import sushi.hardcore.droidfs.GocryptfsVolume import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
@ -129,7 +129,7 @@ class FileOperationService : Service() {
val dstFileHandle = encryptedVolume.openFile(dstPath) val dstFileHandle = encryptedVolume.openFile(dstPath)
if (dstFileHandle != -1L) { if (dstFileHandle != -1L) {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
var length: Int var length: Int
while (remoteEncryptedVolume.read(srcFileHandle, ioBuffer, offset).also { length = it } > 0) { while (remoteEncryptedVolume.read(srcFileHandle, ioBuffer, offset).also { length = it } > 0) {
val written = encryptedVolume.write(dstFileHandle, offset, ioBuffer, length).toLong() val written = encryptedVolume.write(dstFileHandle, offset, ioBuffer, length).toLong()

View File

@ -6,7 +6,6 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import sushi.hardcore.droidfs.BaseActivity import sushi.hardcore.droidfs.BaseActivity
import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.GocryptfsVolume
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement

View File

@ -3,12 +3,11 @@ package sushi.hardcore.droidfs.file_viewers
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import sushi.hardcore.droidfs.GocryptfsVolume import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
@ -73,7 +72,7 @@ class TextEditor: FileViewerActivity() {
if (fileHandle != -1L) { if (fileHandle != -1L) {
val buff = ByteArrayInputStream(content) val buff = ByteArrayInputStream(content)
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
var length: Int var length: Int
while (buff.read(ioBuffer).also { length = it } > 0) { while (buff.read(ioBuffer).also { length = it } > 0) {
val written = encryptedVolume.write(fileHandle, offset, ioBuffer, length).toLong() val written = encryptedVolume.write(fileHandle, offset, ioBuffer, length).toLong()

View File

@ -1,7 +1,6 @@
package sushi.hardcore.droidfs.filesystems package sushi.hardcore.droidfs.filesystems
import android.os.Parcel import android.os.Parcel
import android.util.Log
import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils

View File

@ -5,7 +5,6 @@ import android.net.Uri
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.GocryptfsVolume
import sushi.hardcore.droidfs.SavedVolume import sushi.hardcore.droidfs.SavedVolume
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
@ -80,7 +79,7 @@ abstract class EncryptedVolume: Parcelable {
fun exportFile(fileHandle: Long, os: OutputStream): Boolean { fun exportFile(fileHandle: Long, os: OutputStream): Boolean {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
var length: Int var length: Int
while (read(fileHandle, ioBuffer, offset).also { length = it } > 0){ while (read(fileHandle, ioBuffer, offset).also { length = it } > 0){
os.write(ioBuffer, 0, length) os.write(ioBuffer, 0, length)
@ -117,7 +116,7 @@ abstract class EncryptedVolume: Parcelable {
if (dstfileHandle != -1L) { if (dstfileHandle != -1L) {
var success = true var success = true
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
var length: Int var length: Int
while (inputStream.read(ioBuffer).also { length = it } > 0) { while (inputStream.read(ioBuffer).also { length = it } > 0) {
val written = write(dstfileHandle, offset, ioBuffer, length).toLong() val written = write(dstfileHandle, offset, ioBuffer, length).toLong()
@ -159,7 +158,7 @@ abstract class EncryptedVolume: Parcelable {
Pair(null, 3) Pair(null, 3)
} else { } else {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(ConstValues.IO_BUFF_SIZE)
var length: Int var length: Int
while (read(fileHandle, ioBuffer, offset).also { length = it } > 0) { while (read(fileHandle, ioBuffer, offset).also { length = it } > 0) {
System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length) System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)

View File

@ -1,14 +1,12 @@
package sushi.hardcore.droidfs package sushi.hardcore.droidfs.filesystems
import android.os.Parcel import android.os.Parcel
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.filesystems.Stat
class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() { class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
private external fun native_close(sessionID: Int) private external fun native_close(sessionID: Int)
private external fun native_is_closed(sessionID: Int): Boolean private external fun native_is_closed(sessionID: Int): Boolean
private external fun native_list_dir(sessionID: Int, dir_path: String): MutableList<ExplorerElement> private external fun native_list_dir(sessionID: Int, dir_path: String): MutableList<ExplorerElement>?
private external fun native_open_read_mode(sessionID: Int, file_path: String): Int private external fun native_open_read_mode(sessionID: Int, file_path: String): Int
private external fun native_open_write_mode(sessionID: Int, file_path: String, mode: Int): Int private external fun native_open_write_mode(sessionID: Int, file_path: String, mode: Int): Int
private external fun native_read_file(sessionID: Int, handleID: Int, offset: Long, buff: ByteArray): Int private external fun native_read_file(sessionID: Int, handleID: Int, offset: Long, buff: ByteArray): Int
@ -24,7 +22,6 @@ class GocryptfsVolume(private val sessionID: Int): EncryptedVolume() {
companion object { companion object {
const val KeyLen = 32 const val KeyLen = 32
const val ScryptDefaultLogN = 16 const val ScryptDefaultLogN = 16
const val DefaultBS = 4096
const val CONFIG_FILE_NAME = "gocryptfs.conf" 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 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 private external fun nativeInit(root_cipher_dir: String, password: ByteArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int

View File

@ -30,7 +30,7 @@ void jbyteArray_to_unsignedCharArray(const jbyte* src, unsigned char* dst, const
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_createVolume(JNIEnv *env, jclass clazz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_00024Companion_createVolume(JNIEnv *env, jclass clazz,
jstring jroot_cipher_dir, jstring jroot_cipher_dir,
jbyteArray jpassword, jbyteArray jpassword,
jboolean plainTextNames, jboolean plainTextNames,
@ -77,7 +77,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_createVolume(JNIEnv *
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_nativeInit(JNIEnv *env, jobject clazz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_00024Companion_nativeInit(JNIEnv *env, jobject clazz,
jstring jroot_cipher_dir, jstring jroot_cipher_dir,
jbyteArray jpassword, jbyteArray jpassword,
jbyteArray jgiven_hash, jbyteArray jgiven_hash,
@ -145,13 +145,13 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_nativeInit(JNIEnv *en
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1is_1closed(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1is_1closed(JNIEnv *env, jobject thiz,
jint sessionID) { jint sessionID) {
return gcf_is_closed(sessionID); return gcf_is_closed(sessionID);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_changePassword(JNIEnv *env, jclass clazz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_00024Companion_changePassword(JNIEnv *env, jclass clazz,
jstring jroot_cipher_dir, jstring jroot_cipher_dir,
jcharArray jold_password, jcharArray jold_password,
jbyteArray jgiven_hash, jbyteArray jgiven_hash,
@ -220,6 +220,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_changePassword(JNIEnv
} }
wipe(new_password, new_password_len); wipe(new_password, new_password_len);
free(new_password);
(*env)->ReleaseCharArrayElements(env, jnew_password, jchar_new_password, 0); (*env)->ReleaseCharArrayElements(env, jnew_password, jchar_new_password, 0);
if (!(*env)->IsSameObject(env, jreturned_hash, NULL)) { if (!(*env)->IsSameObject(env, jreturned_hash, NULL)) {
@ -233,12 +234,12 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_00024Companion_changePassword(JNIEnv
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1close(JNIEnv *env, jobject thiz, jint sessionID) { Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1close(JNIEnv *env, jobject thiz, jint sessionID) {
gcf_close(sessionID); gcf_close(sessionID);
} }
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1list_1dir(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1list_1dir(JNIEnv *env, jobject thiz,
jint sessionID, jstring jplain_dir) { jint sessionID, jstring jplain_dir) {
const char* plain_dir = (*env)->GetStringUTFChars(env, jplain_dir, NULL); const char* plain_dir = (*env)->GetStringUTFChars(env, jplain_dir, NULL);
const size_t plain_dir_len = strlen(plain_dir); const size_t plain_dir_len = strlen(plain_dir);
@ -246,55 +247,59 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1list_1dir(JNIEnv *env, jobje
struct gcf_list_dir_return elements = gcf_list_dir(sessionID, go_plain_dir); struct gcf_list_dir_return elements = gcf_list_dir(sessionID, go_plain_dir);
jclass java_ArrayList = (*env)->NewLocalRef(env, (*env)->FindClass(env, "java/util/ArrayList")); jobject elementList = NULL;
jmethodID java_ArrayList_init = (*env)->GetMethodID(env, java_ArrayList, "<init>", "(I)V"); if (elements.r0 != NULL) {
jmethodID java_ArrayList_add = (*env)->GetMethodID(env, java_ArrayList, "add", "(Ljava/lang/Object;)Z"); jclass arrayList = (*env)->NewLocalRef(env, (*env)->FindClass(env, "java/util/ArrayList"));
jmethodID arrayListInit = (*env)->GetMethodID(env, arrayList, "<init>", "(I)V");
jmethodID arrayListAdd = (*env)->GetMethodID(env, arrayList, "add", "(Ljava/lang/Object;)Z");
jclass classExplorerElement = (*env)->NewLocalRef(env, (*env)->FindClass(env, "sushi/hardcore/droidfs/explorers/ExplorerElement"));
jmethodID explorerElementNew = (*env)->GetStaticMethodID(env, classExplorerElement, "new", "(Ljava/lang/String;IJJLjava/lang/String;)Lsushi/hardcore/droidfs/explorers/ExplorerElement;");
elementList = (*env)->NewObject(env, arrayList, arrayListInit, elements.r2);
jclass classExplorerElement = (*env)->NewLocalRef(env, (*env)->FindClass(env, "sushi/hardcore/droidfs/explorers/ExplorerElement")); unsigned int c = 0;
jmethodID explorerElement_new = (*env)->GetStaticMethodID(env, classExplorerElement, "new", "(Ljava/lang/String;IJJLjava/lang/String;)Lsushi/hardcore/droidfs/explorers/ExplorerElement;"); for (unsigned int i=0; i<elements.r2; ++i){
jobject element_list = (*env)->NewObject(env, java_ArrayList, java_ArrayList_init, elements.r2); const char* name = &(elements.r0[c]);
unsigned int c = 0; size_t nameLen = strlen(name);
for (unsigned int i=0; i<elements.r2; ++i){
const char* name = &(elements.r0[c]);
size_t name_len = strlen(name);
const char gcf_full_path[plain_dir_len+name_len+2]; char* fullPath = malloc(sizeof(char) * (plain_dir_len + nameLen + 2));
strcpy(gcf_full_path, plain_dir); strcpy(fullPath, plain_dir);
if (plain_dir[-2] != '/') { if (plain_dir[-2] != '/') {
strcat(gcf_full_path, "/"); strcat(fullPath, "/");
}
strcat(fullPath, name);
GoString go_name = {fullPath, strlen(fullPath)};
struct gcf_get_attrs_return attrs = gcf_get_attrs(sessionID, go_name);
free(fullPath);
jstring jname = (*env)->NewStringUTF(env, name);
jobject explorerElement = (*env)->CallStaticObjectMethod(
env,
classExplorerElement,
explorerElementNew,
jname,
elements.r1[i],
(long long) attrs.r1,
(long long) attrs.r2,
jplain_dir
);
(*env)->CallBooleanMethod(env, elementList, arrayListAdd, explorerElement);
(*env)->DeleteLocalRef(env, explorerElement);
(*env)->DeleteLocalRef(env, jname);
c += nameLen + 1;
} }
strcat(gcf_full_path, name);
GoString go_name = {gcf_full_path, strlen(gcf_full_path)}; free(elements.r0);
struct gcf_get_attrs_return attrs = gcf_get_attrs(sessionID, go_name); free(elements.r1);
jstring jname = (*env)->NewStringUTF(env, name);
jobject explorerElement = (*env)->CallStaticObjectMethod(
env,
classExplorerElement,
explorerElement_new,
jname,
elements.r1[i],
(long long) attrs.r1,
attrs.r2,
jplain_dir
);
(*env)->CallBooleanMethod(env, element_list, java_ArrayList_add, explorerElement);
(*env)->DeleteLocalRef(env, explorerElement);
(*env)->DeleteLocalRef(env, jname);
c += name_len+1;
} }
free(elements.r0);
free(elements.r1);
(*env)->ReleaseStringUTFChars(env, jplain_dir, plain_dir); (*env)->ReleaseStringUTFChars(env, jplain_dir, plain_dir);
return element_list; return elementList;
} }
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1get_1attr(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1get_1attr(JNIEnv *env, jobject thiz,
jint sessionID, jstring jfile_path) { jint sessionID, jstring jfile_path) {
const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL); const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL);
GoString go_file_path = {file_path, strlen(file_path)}; GoString go_file_path = {file_path, strlen(file_path)};
@ -318,7 +323,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1get_1attr(JNIEnv *env, jobje
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1open_1read_1mode(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1open_1read_1mode(JNIEnv *env, jobject thiz,
jint sessionID, jint sessionID,
jstring jfile_path) { jstring jfile_path) {
const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL); const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL);
@ -332,7 +337,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1open_1read_1mode(JNIEnv *env
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1open_1write_1mode(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1open_1write_1mode(JNIEnv *env, jobject thiz,
jint sessionID, jint sessionID,
jstring jfile_path, jstring jfile_path,
jint mode) { jint mode) {
@ -347,7 +352,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1open_1write_1mode(JNIEnv *en
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1write_1file(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1write_1file(JNIEnv *env, jobject thiz,
jint sessionID, jint handleID, jlong offset, jint sessionID, jint handleID, jlong offset,
jbyteArray jbuff, jint buff_size) { jbyteArray jbuff, jint buff_size) {
jbyte* buff = (*env)->GetByteArrayElements(env, jbuff, NULL); jbyte* buff = (*env)->GetByteArrayElements(env, jbuff, NULL);
@ -361,24 +366,24 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1write_1file(JNIEnv *env, job
} }
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1read_1file(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1read_1file(JNIEnv *env, jobject thiz,
jint sessionID, jint handleID, jlong offset, jint sessionID, jint handleID, jlong offset,
jbyteArray jbuff) { jbyteArray jbuff) {
const size_t buff_size = (*env)->GetArrayLength(env, jbuff); const size_t buff_size = (*env)->GetArrayLength(env, jbuff);
unsigned char buff[buff_size]; unsigned char* buff = malloc(sizeof(char)*buff_size);
GoSlice go_buff = {buff, buff_size, buff_size}; GoSlice go_buff = {buff, buff_size, buff_size};
int read = gcf_read_file(sessionID, handleID, offset, go_buff); int read = gcf_read_file(sessionID, handleID, offset, go_buff);
if (read > 0){ if (read > 0){
(*env)->SetByteArrayRegion(env, jbuff, 0, read, buff); (*env)->SetByteArrayRegion(env, jbuff, 0, read, (const jbyte*)buff);
} }
free(buff);
return read; return read;
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1truncate(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1truncate(JNIEnv *env, jobject thiz,
jint sessionID, jint sessionID,
jstring jpath, jstring jpath,
jlong offset) { jlong offset) {
@ -392,14 +397,14 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1truncate(JNIEnv *env, jobjec
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1close_1file(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1close_1file(JNIEnv *env, jobject thiz,
jint sessionID, jint sessionID,
jint handleID) { jint handleID) {
gcf_close_file(sessionID, handleID); gcf_close_file(sessionID, handleID);
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1remove_1file(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1remove_1file(JNIEnv *env, jobject thiz,
jint sessionID, jstring jfile_path) { jint sessionID, jstring jfile_path) {
const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL); const char* file_path = (*env)->GetStringUTFChars(env, jfile_path, NULL);
GoString go_file_path = {file_path, strlen(file_path)}; GoString go_file_path = {file_path, strlen(file_path)};
@ -412,7 +417,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1remove_1file(JNIEnv *env, jo
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1mkdir(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1mkdir(JNIEnv *env, jobject thiz,
jint sessionID, jstring jdir_path, jint mode) { jint sessionID, jstring jdir_path, jint mode) {
const char* dir_path = (*env)->GetStringUTFChars(env, jdir_path, NULL); const char* dir_path = (*env)->GetStringUTFChars(env, jdir_path, NULL);
GoString go_dir_path = {dir_path, strlen(dir_path)}; GoString go_dir_path = {dir_path, strlen(dir_path)};
@ -425,7 +430,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1mkdir(JNIEnv *env, jobject t
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1rmdir(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1rmdir(JNIEnv *env, jobject thiz,
jint sessionID, jstring jdir_path) { jint sessionID, jstring jdir_path) {
const char* dir_path = (*env)->GetStringUTFChars(env, jdir_path, NULL); const char* dir_path = (*env)->GetStringUTFChars(env, jdir_path, NULL);
GoString go_dir_path = {dir_path, strlen(dir_path)}; GoString go_dir_path = {dir_path, strlen(dir_path)};
@ -438,7 +443,7 @@ Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1rmdir(JNIEnv *env, jobject t
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_GocryptfsVolume_native_1rename(JNIEnv *env, jobject thiz, Java_sushi_hardcore_droidfs_filesystems_GocryptfsVolume_native_1rename(JNIEnv *env, jobject thiz,
jint sessionID, jstring jold_path, jint sessionID, jstring jold_path,
jstring jnew_path) { jstring jnew_path) {
const char* old_path = (*env)->GetStringUTFChars(env, jold_path, NULL); const char* old_path = (*env)->GetStringUTFChars(env, jold_path, NULL);

View File

@ -1,9 +1,4 @@
<resources> <resources>
<string-array name="volume_types">
<item>Gocryptfs</item>
<item>CryFS</item>
</string-array>
<string-array name="gocryptfs_encryption_ciphers"> <string-array name="gocryptfs_encryption_ciphers">
<item>AES-GCM</item> <item>AES-GCM</item>
<item>XChaCha20-Poly1305</item> <item>XChaCha20-Poly1305</item>

View File

@ -242,4 +242,8 @@
<string name="pin_passwords_title">Numeric keypad layout</string> <string name="pin_passwords_title">Numeric keypad layout</string>
<string name="pin_passwords_summary">Use a numeric keypad layout when entering volume passwords</string> <string name="pin_passwords_summary">Use a numeric keypad layout when entering volume passwords</string>
<string name="volume_type_label">Volume type:</string> <string name="volume_type_label">Volume type:</string>
<string name="gocryptfs">Gocryptfs</string>
<string name="cryfs">CryFS</string>
<string name="gocryptfs_disabled">Gocryptfs support has been disabled</string>
<string name="cryfs_disabled">CryFS support has been disabled</string>
</resources> </resources>