diff options
| -rw-r--r-- | Documentation/MANPAGE.md | 10 | ||||
| -rw-r--r-- | cli_args.go | 6 | ||||
| -rw-r--r-- | gocryptfs-xray/xray_main.go | 2 | ||||
| -rw-r--r-- | init_dir.go | 3 | ||||
| -rw-r--r-- | internal/configfile/config_file.go | 7 | ||||
| -rw-r--r-- | internal/fido2/fido2.go | 18 | ||||
| -rw-r--r-- | main.go | 2 | 
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) @@ -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 {  | 
