diff --git a/android/app/src/main/kotlin/net/defined/mobile_nebula/EncFile.kt b/android/app/src/main/kotlin/net/defined/mobile_nebula/EncFile.kt index 5cbc2be..e9a641d 100644 --- a/android/app/src/main/kotlin/net/defined/mobile_nebula/EncFile.kt +++ b/android/app/src/main/kotlin/net/defined/mobile_nebula/EncFile.kt @@ -1,22 +1,57 @@ package net.defined.mobile_nebula import android.content.Context +import android.util.Log import androidx.security.crypto.EncryptedFile import androidx.security.crypto.MasterKeys import java.io.* +import java.security.KeyStore class EncFile(private val context: Context) { + companion object { + // Borrowed from androidx.security.crypto.MasterKeys + private const val ANDROID_KEYSTORE = "AndroidKeyStore" + + // Borrowed from androidx.security.crypto.EncryptedFile + private const val KEYSET_PREF_NAME = "__androidx_security_crypto_encrypted_file_pref__" + } + private val scheme = EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB - private val master: String = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) + private val spec = MasterKeys.AES256_GCM_SPEC + private var master: String = MasterKeys.getOrCreate(spec) fun openRead(file: File): BufferedReader { - val eFile = EncryptedFile.Builder(file, context, master, scheme).build() - return eFile.openFileInput().bufferedReader() + // We may fail to decrypt the file, in which case we'll raise an exception. + // Callers should handle this exception by deleting the invalid file. + return build(file).openFileInput().bufferedReader() } fun openWrite(file: File): BufferedWriter { - val eFile = EncryptedFile.Builder(file, context, master, scheme).build() - return eFile.openFileOutput().bufferedWriter() + return try { + build(file).openFileOutput().bufferedWriter() + } catch (e: Exception) { + // If we fail to open the file, it's likely because the master key no longer works. + // We'll try to reset the master key and try again. + resetMasterKey() + + build(file).openFileOutput().bufferedWriter() + } } + private fun build(file: File): EncryptedFile { + return EncryptedFile.Builder(file, context, master, scheme).build() + } + + fun resetMasterKey() { + // Reset the master key + KeyStore.getInstance(ANDROID_KEYSTORE).apply { + load(null) + deleteEntry(master) + } + // And reset the shared preference containing the file encryption key + context.deleteSharedPreferences(KEYSET_PREF_NAME) + + // Re-create the master key now so future calls don't fail + master = MasterKeys.getOrCreate(spec) + } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt b/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt index 90c7b9b..dd83799 100644 --- a/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt +++ b/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt @@ -84,6 +84,10 @@ class MainActivity: FlutterActivity() { "active.setRemoteForTunnel" -> activeSetRemoteForTunnel(call, result) "active.closeTunnel" -> activeCloseTunnel(call, result) + "debug.clearKeys" -> { + EncFile(context).resetMasterKey() + } + else -> result.notImplemented() } } diff --git a/android/build.gradle b/android/build.gradle index 3c12826..9444e0b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -30,6 +30,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/lib/screens/MainScreen.dart b/lib/screens/MainScreen.dart index 7712d9a..337d0b1 100644 --- a/lib/screens/MainScreen.dart +++ b/lib/screens/MainScreen.dart @@ -119,7 +119,7 @@ class _MainScreenState extends State { children: [ _debugSave(badDebugSave), _debugSave(goodDebugSave), - _debugDNEnroll(), + _debugClearKeys(), ], mainAxisAlignment: MainAxisAlignment.center, ); @@ -289,15 +289,16 @@ class _MainScreenState extends State { ); } - Widget _debugDNEnroll() { + Widget _debugClearKeys() { return CupertinoButton( - child: Text('DN Enroll'), - onPressed: () => Utils.openPage(context, (context) { - return EnrollmentScreen(allowCodeEntry: true); - }), + child: Text("Clear Keys"), + onPressed: () async { + await platform.invokeMethod("debug.clearKeys", null); + }, ); } + _loadSites() async { //TODO: This can throw, we need to show an error dialog Map rawSites = jsonDecode(await platform.invokeMethod('listSites')); diff --git a/nebula/go.mod b/nebula/go.mod index 3122f02..902c105 100644 --- a/nebula/go.mod +++ b/nebula/go.mod @@ -8,7 +8,7 @@ require ( github.com/DefinedNet/dnapi v0.0.0-20221117210952-6f56f055f991 github.com/sirupsen/logrus v1.9.2 github.com/slackhq/nebula v1.7.2 - golang.org/x/crypto v0.9.0 + golang.org/x/crypto v0.16.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -34,11 +34,13 @@ require ( github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect github.com/vishvananda/netlink v1.1.0 // indirect github.com/vishvananda/netns v0.0.4 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/tools v0.9.1 // indirect + golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/tools v0.16.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard/windows v0.5.3 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/nebula/go.sum b/nebula/go.sum index 9107c5c..af7b1ea 100644 --- a/nebula/go.sum +++ b/nebula/go.sum @@ -148,12 +148,22 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da h1:gS9sVMAeHM+gVBmM9bTM6vUi/NHv58O3QzJ3vjjN84M= +golang.org/x/mobile v0.0.0-20231108233038-35478a0c49da/go.mod h1:IEceR0jfVklLJXrbUe90rfdAFAYDW0SQwKl4qvO1GBQ= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a h1:sYbmY3FwUWCBTodZL1S3JUuOvaW6kM2o+clDzzDNBWg= +golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a/go.mod h1:Ede7gF0KGoHlj822RtphAHK1jLdrcuRBZg0sF1Q+SPc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -166,6 +176,10 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -174,6 +188,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -191,9 +207,17 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -204,6 +228,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pubspec.lock b/pubspec.lock index 0be5c11..df2e762 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,21 +42,21 @@ packages: name: cross_file url: "https://pub.dartlang.org" source: hosted - version: "0.3.3+2" + version: "0.3.3+4" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.0.5" fake_async: dependency: transitive description: @@ -70,21 +70,21 @@ packages: name: ffi url: "https://pub.dartlang.org" source: hosted - version: "2.0.1" + version: "2.0.2" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.2" + version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker url: "https://pub.dartlang.org" source: hosted - version: "5.2.2" + version: "5.2.10" flutter: dependency: "direct main" description: flutter @@ -103,21 +103,21 @@ packages: name: flutter_platform_widgets url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.2.6" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.0.15" flutter_svg: dependency: "direct main" description: name: flutter_svg url: "https://pub.dartlang.org" source: hosted - version: "1.1.5" + version: "1.1.6" flutter_test: dependency: "direct dev" description: flutter @@ -169,7 +169,7 @@ packages: name: mime url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "1.0.4" package_info: dependency: "direct main" description: @@ -204,77 +204,63 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.1.0" path_provider_android: dependency: transitive description: name: path_provider_android url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" - path_provider_ios: + version: "2.1.0" + path_provider_foundation: dependency: transitive description: - name: path_provider_ios + name: path_provider_foundation url: "https://pub.dartlang.org" source: hosted - version: "2.0.7" + version: "2.3.0" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" + version: "2.2.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.1.0" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.2.0" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "5.0.0" + version: "5.1.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.4" + version: "2.1.5" pull_to_refresh: dependency: "direct main" description: @@ -288,14 +274,14 @@ packages: name: share_plus url: "https://pub.dartlang.org" source: hosted - version: "6.3.0" + version: "6.3.4" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.2.0" + version: "3.3.1" sky_engine: dependency: transitive description: flutter @@ -349,63 +335,63 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.1.6" + version: "6.1.11" url_launcher_android: dependency: transitive description: name: url_launcher_android url: "https://pub.dartlang.org" source: hosted - version: "6.0.13" + version: "6.0.38" url_launcher_ios: dependency: transitive description: name: url_launcher_ios url: "https://pub.dartlang.org" source: hosted - version: "6.0.13" + version: "6.1.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.5" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.13" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.0.7" uuid: dependency: "direct main" description: @@ -426,14 +412,14 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "3.1.1" + version: "3.1.4" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "1.0.2" xml: dependency: transitive description: @@ -443,4 +429,4 @@ packages: version: "6.1.0" sdks: dart: ">=2.18.1 <3.0.0" - flutter: ">=3.0.0" + flutter: ">=3.3.0"