aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorinvis-z2023-11-21 18:12:01 +0000
committerrfjakob2024-04-19 22:36:55 +0200
commit4b6b9553c4a2e14fd809754f6bf187957ff3cdfd (patch)
treec020acb7b2ebfb6121725082ec03944c8a6aa1cd
parentf5007b28c366d1a9671146710975679a154f30f8 (diff)
Add option to set FIDO2 verificatoin option
Add an option to specify user verification options for `fido2-assert -t` Options will be saved to config file Provide same functionality to #705 with simpler implementation Resolve #702
-rw-r--r--Documentation/MANPAGE.md10
-rw-r--r--cli_args.go6
-rw-r--r--gocryptfs-xray/xray_main.go2
-rw-r--r--init_dir.go3
-rw-r--r--internal/configfile/config_file.go7
-rw-r--r--internal/fido2/fido2.go18
-rw-r--r--main.go2
7 files changed, 35 insertions, 13 deletions
diff --git a/Documentation/MANPAGE.md b/Documentation/MANPAGE.md
index 8c4af3f..9caa359 100644
--- a/Documentation/MANPAGE.md
+++ b/Documentation/MANPAGE.md
@@ -482,11 +482,17 @@ for details.
#### -fido2 DEVICE_PATH
Use a FIDO2 token to initialize and unlock the filesystem.
-Use "fido2-token -L" to obtain the FIDO2 token device path.
-For linux, "fido2-tools" package is needed.
+Use `fido2-token -L` to obtain the FIDO2 token device path.
+For linux, **fido2-tools** package is needed.
Applies to: all actions that ask for a password.
+#### -fido2-assert-option OPTION
+Options passed to `fido2-assert` with `-t` option.
+This option may be specified multiple times, each time it will add two
+arguements `-t` `OPTION` to `fido2-assert`.
+See `man fido2-assert` to check supported options.
+
#### -masterkey string
Use an explicit master key specified on the command line or, if the special
value "stdin" is used, read the masterkey from stdin, instead of reading
diff --git a/cli_args.go b/cli_args.go
index 75df4d1..2e9e796 100644
--- a/cli_args.go
+++ b/cli_args.go
@@ -35,7 +35,10 @@ type argContainer struct {
// Mount options with opposites
dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool
masterkey, mountpoint, cipherdir, cpuprofile,
- memprofile, ko, ctlsock, fsname, force_owner, trace, fido2 string
+ memprofile, ko, ctlsock, fsname, force_owner, trace string
+ // FIDO2
+ fido2 string
+ fido2_assert_options []string
// -extpass, -badname, -passfile can be passed multiple times
extpass, badname, passfile []string
// For reverse mode, several ways to specify exclusions. All can be specified multiple times.
@@ -208,6 +211,7 @@ func parseCliOpts(osArgs []string) (args argContainer) {
flagSet.StringVar(&args.force_owner, "force_owner", "", "uid:gid pair to coerce ownership")
flagSet.StringVar(&args.trace, "trace", "", "Write execution trace to file")
flagSet.StringVar(&args.fido2, "fido2", "", "Protect the masterkey using a FIDO2 token instead of a password")
+ flagSet.StringArrayVar(&args.fido2_assert_options, "fido2-assert-option", nil, "Options to be passed with `fido2-assert -t`")
// Exclusion options
flagSet.StringArrayVar(&args.exclude, "e", nil, "Alias for -exclude")
diff --git a/gocryptfs-xray/xray_main.go b/gocryptfs-xray/xray_main.go
index 2bc98f0..1c491f1 100644
--- a/gocryptfs-xray/xray_main.go
+++ b/gocryptfs-xray/xray_main.go
@@ -146,7 +146,7 @@ func dumpMasterKey(fn string, fido2Path string) {
tlog.Fatal.Printf("Masterkey encrypted using FIDO2 token; need to use the --fido2 option.")
os.Exit(exitcodes.Usage)
}
- pw = fido2.Secret(fido2Path, cf.FIDO2.CredentialID, cf.FIDO2.HMACSalt)
+ pw = fido2.Secret(fido2Path, cf.FIDO2.AssertOptions, cf.FIDO2.CredentialID, cf.FIDO2.HMACSalt)
} else {
pw, err = readpassword.Once(nil, nil, "")
if err != nil {
diff --git a/init_dir.go b/init_dir.go
index 738590f..9ba1a01 100644
--- a/init_dir.go
+++ b/init_dir.go
@@ -84,7 +84,7 @@ func initDir(args *argContainer) {
if args.fido2 != "" {
fido2CredentialID = fido2.Register(args.fido2, filepath.Base(args.cipherdir))
fido2HmacSalt = cryptocore.RandBytes(32)
- password = fido2.Secret(args.fido2, fido2CredentialID, fido2HmacSalt)
+ password = fido2.Secret(args.fido2, args.fido2_assert_options, fido2CredentialID, fido2HmacSalt)
} else {
// normal password entry
password, err = readpassword.Twice([]string(args.extpass), []string(args.passfile))
@@ -105,6 +105,7 @@ func initDir(args *argContainer) {
AESSIV: args.aessiv,
Fido2CredentialID: fido2CredentialID,
Fido2HmacSalt: fido2HmacSalt,
+ Fido2AssertOptions: args.fido2_assert_options,
DeterministicNames: args.deterministic_names,
XChaCha20Poly1305: args.xchacha,
LongNameMax: args.longnamemax,
diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go
index 3d59dc5..995a0c8 100644
--- a/internal/configfile/config_file.go
+++ b/internal/configfile/config_file.go
@@ -33,6 +33,7 @@ type FIDO2Params struct {
CredentialID []byte
// FIDO2 hmac-secret salt
HMACSalt []byte
+ AssertOptions []string
}
// ConfFile is the content of a config file.
@@ -71,6 +72,7 @@ type CreateArgs struct {
AESSIV bool
Fido2CredentialID []byte
Fido2HmacSalt []byte
+ Fido2AssertOptions []string
DeterministicNames bool
XChaCha20Poly1305 bool
LongNameMax uint8
@@ -117,8 +119,9 @@ func Create(args *CreateArgs) error {
if len(args.Fido2CredentialID) > 0 {
cf.setFeatureFlag(FlagFIDO2)
cf.FIDO2 = &FIDO2Params{
- CredentialID: args.Fido2CredentialID,
- HMACSalt: args.Fido2HmacSalt,
+ CredentialID: args.Fido2CredentialID,
+ HMACSalt: args.Fido2HmacSalt,
+ AssertOptions: args.Fido2AssertOptions,
}
}
// Catch bugs and invalid cli flag combinations early
diff --git a/internal/fido2/fido2.go b/internal/fido2/fido2.go
index fa6015e..e08e589 100644
--- a/internal/fido2/fido2.go
+++ b/internal/fido2/fido2.go
@@ -35,13 +35,21 @@ func (fc fidoCommand) String() string {
const relyingPartyID = "gocryptfs"
-func callFidoCommand(command fidoCommand, device string, stdin []string) ([]string, error) {
+func callFidoCommand(command fidoCommand, assertOptions []string, device string, stdin []string) ([]string, error) {
var cmd *exec.Cmd
switch command {
case cred:
cmd = exec.Command("fido2-cred", "-M", "-h", device)
case assert:
- cmd = exec.Command("fido2-assert", "-G", "-h", device)
+ var args []string
+ args = append(args, "-G")
+ args = append(args, "-h")
+ for i := range assertOptions{
+ args = append(args, "-t")
+ args = append(args, assertOptions[i])
+ }
+ args = append(args, device)
+ cmd = exec.Command("fido2-assert", args...)
}
tlog.Debug.Printf("callFidoCommand %s: executing %q with args %q", command, cmd.Path, cmd.Args)
cmd.Stderr = os.Stderr
@@ -67,7 +75,7 @@ func Register(device string, userName string) (credentialID []byte) {
cdh := base64.StdEncoding.EncodeToString(cryptocore.RandBytes(32))
userID := base64.StdEncoding.EncodeToString(cryptocore.RandBytes(32))
stdin := []string{cdh, relyingPartyID, userName, userID}
- out, err := callFidoCommand(cred, device, stdin)
+ out, err := callFidoCommand(cred, nil, device, stdin)
if err != nil {
tlog.Fatal.Println(err)
os.Exit(exitcodes.FIDO2Error)
@@ -81,14 +89,14 @@ func Register(device string, userName string) (credentialID []byte) {
}
// Secret generates a HMAC secret using a FIDO2 token
-func Secret(device string, credentialID []byte, salt []byte) (secret []byte) {
+func Secret(device string, assertOptions []string, credentialID []byte, salt []byte) (secret []byte) {
tlog.Info.Printf("FIDO2 Secret: interact with your device ...")
cdh := base64.StdEncoding.EncodeToString(cryptocore.RandBytes(32))
crid := base64.StdEncoding.EncodeToString(credentialID)
hmacsalt := base64.StdEncoding.EncodeToString(salt)
stdin := []string{cdh, relyingPartyID, crid, hmacsalt}
// call fido2-assert
- out, err := callFidoCommand(assert, device, stdin)
+ out, err := callFidoCommand(assert, assertOptions, device, stdin)
if err != nil {
tlog.Fatal.Println(err)
os.Exit(exitcodes.FIDO2Error)
diff --git a/main.go b/main.go
index 7facf78..bb4c4e2 100644
--- a/main.go
+++ b/main.go
@@ -43,7 +43,7 @@ func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile,
tlog.Fatal.Printf("Masterkey encrypted using FIDO2 token; need to use the --fido2 option.")
return nil, nil, exitcodes.NewErr("", exitcodes.Usage)
}
- pw = fido2.Secret(args.fido2, cf.FIDO2.CredentialID, cf.FIDO2.HMACSalt)
+ pw = fido2.Secret(args.fido2, cf.FIDO2.AssertOptions, cf.FIDO2.CredentialID, cf.FIDO2.HMACSalt)
} else {
pw, err = readpassword.Once([]string(args.extpass), []string(args.passfile), "")
if err != nil {