Skip to content

Commit

Permalink
Add option to set FIDO2 verificatoin option
Browse files Browse the repository at this point in the history
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
  • Loading branch information
invis-z authored and rfjakob committed Apr 19, 2024
1 parent f5007b2 commit 4b6b955
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 13 deletions.
10 changes: 8 additions & 2 deletions Documentation/MANPAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion cli_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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")
Expand Down
2 changes: 1 addition & 1 deletion gocryptfs-xray/xray_main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion init_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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,
Expand Down
7 changes: 5 additions & 2 deletions internal/configfile/config_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -71,6 +72,7 @@ type CreateArgs struct {
AESSIV bool
Fido2CredentialID []byte
Fido2HmacSalt []byte
Fido2AssertOptions []string
DeterministicNames bool
XChaCha20Poly1305 bool
LongNameMax uint8
Expand Down Expand Up @@ -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
Expand Down
18 changes: 13 additions & 5 deletions internal/fido2/fido2.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 4b6b955

Please sign in to comment.