diff options
| -rw-r--r-- | cli-tests/t_encrypt_raw_key.out | 48 | ||||
| -rwxr-xr-x | cli-tests/t_encrypt_raw_key.sh | 19 | ||||
| -rw-r--r-- | cmd/fscrypt/keys.go | 46 |
3 files changed, 92 insertions, 21 deletions
diff --git a/cli-tests/t_encrypt_raw_key.out b/cli-tests/t_encrypt_raw_key.out index 8765ba2..1f51dc0 100644 --- a/cli-tests/t_encrypt_raw_key.out +++ b/cli-tests/t_encrypt_raw_key.out @@ -1,5 +1,5 @@ -# Encrypt with raw_key protector +# Encrypt with raw_key protector from file ext4 filesystem "MNT" has 1 protector and 1 policy PROTECTOR LINKED DESCRIPTION @@ -17,9 +17,53 @@ Protected with 1 protector: PROTECTOR LINKED DESCRIPTION desc1 No raw key protector "prot" -# Try to encrypt with raw_key protector, using wrong key length +# Encrypt with raw_key protector from stdin +ext4 filesystem "MNT" has 1 protector and 1 policy + +PROTECTOR LINKED DESCRIPTION +desc6 No raw key protector "prot" + +POLICY UNLOCKED PROTECTORS +desc7 Yes desc6 +"MNT/dir" is encrypted with fscrypt. + +Policy: desc7 +Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2 +Unlocked: Yes + +Protected with 1 protector: +PROTECTOR LINKED DESCRIPTION +desc6 No raw key protector "prot" + +# Try to encrypt with raw_key protector from file, using wrong key length [ERROR] fscrypt encrypt: TMPDIR/raw_key: key file must be 32 bytes ext4 filesystem "MNT" has 0 protectors and 0 policies [ERROR] fscrypt status: file or directory "MNT/dir" is not encrypted + +# Try to encrypt with raw_key protector from stdin, using wrong key length +[ERROR] fscrypt encrypt: unexpected EOF +ext4 filesystem "MNT" has 0 protectors and 0 policies + +[ERROR] fscrypt status: file or directory "MNT/dir" is not + encrypted + +# Encrypt with raw_key protector from file, unlock from stdin +"MNT/dir" is now locked. +ext4 filesystem "MNT" has 1 protector and 1 policy + +PROTECTOR LINKED DESCRIPTION +desc11 No raw key protector "prot" + +POLICY UNLOCKED PROTECTORS +desc12 Yes desc11 +"MNT/dir" is encrypted with fscrypt. + +Policy: desc12 +Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2 +Unlocked: Yes + +Protected with 1 protector: +PROTECTOR LINKED DESCRIPTION +desc11 No raw key protector "prot" diff --git a/cli-tests/t_encrypt_raw_key.sh b/cli-tests/t_encrypt_raw_key.sh index 260b094..e5c6d20 100755 --- a/cli-tests/t_encrypt_raw_key.sh +++ b/cli-tests/t_encrypt_raw_key.sh @@ -27,12 +27,27 @@ show_status() fi } -begin "Encrypt with raw_key protector" +begin "Encrypt with raw_key protector from file" head -c 32 /dev/urandom > "$raw_key_file" fscrypt encrypt --quiet --name=prot --source=raw_key --key="$raw_key_file" "$dir" show_status true -begin "Try to encrypt with raw_key protector, using wrong key length" +begin "Encrypt with raw_key protector from stdin" +head -c 32 /dev/urandom | fscrypt encrypt --quiet --name=prot --source=raw_key "$dir" +show_status true + +begin "Try to encrypt with raw_key protector from file, using wrong key length" head -c 16 /dev/urandom > "$raw_key_file" _expect_failure "fscrypt encrypt --quiet --name=prot --source=raw_key --key='$raw_key_file' '$dir'" show_status false + +begin "Try to encrypt with raw_key protector from stdin, using wrong key length" +_expect_failure "head -c 16 /dev/urandom | fscrypt encrypt --quiet --name=prot --source=raw_key '$dir'" +show_status false + +begin "Encrypt with raw_key protector from file, unlock from stdin" +head -c 32 /dev/urandom > "$raw_key_file" +fscrypt encrypt --quiet --name=prot --source=raw_key --key="$raw_key_file" "$dir" +fscrypt lock "$dir" +fscrypt unlock --quiet "$dir" < "$raw_key_file" +show_status true diff --git a/cmd/fscrypt/keys.go b/cmd/fscrypt/keys.go index cb86404..b57c01d 100644 --- a/cmd/fscrypt/keys.go +++ b/cmd/fscrypt/keys.go @@ -22,6 +22,7 @@ package main import ( + "bufio" "fmt" "io" "log" @@ -106,6 +107,33 @@ func getPassphraseKey(prompt string) (*crypto.Key, error) { return crypto.NewKeyFromReader(passphraseReader{}) } +func makeRawKey(info actions.ProtectorInfo) (*crypto.Key, error) { + // When running non-interactively and no key was provided, + // try to read it from stdin + if keyFileFlag.Value == "" && !term.IsTerminal(stdinFd) { + return crypto.NewFixedLengthKeyFromReader(bufio.NewReader(os.Stdin), + metadata.InternalKeyLen) + } + + prompt := fmt.Sprintf("Enter key file for protector %q: ", info.Name()) + // Raw keys use a file containing the key data. + file, err := promptForKeyFile(prompt) + if err != nil { + return nil, err + } + defer file.Close() + + fileInfo, err := file.Stat() + if err != nil { + return nil, err + } + + if fileInfo.Size() != metadata.InternalKeyLen { + return nil, errors.Wrap(ErrKeyFileLength, file.Name()) + } + return crypto.NewFixedLengthKeyFromReader(file, metadata.InternalKeyLen) +} + // makeKeyFunc creates an actions.KeyFunc. This function customizes the KeyFunc // to whether or not it supports retrying, whether it confirms the passphrase, // and custom prefix for printing (if any). @@ -179,23 +207,7 @@ func makeKeyFunc(supportRetry, shouldConfirm bool, prefix string) actions.KeyFun if prefix != "" { return nil, ErrNotPassphrase } - prompt := fmt.Sprintf("Enter key file for protector %q: ", info.Name()) - // Raw keys use a file containing the key data. - file, err := promptForKeyFile(prompt) - if err != nil { - return nil, err - } - defer file.Close() - - fileInfo, err := file.Stat() - if err != nil { - return nil, err - } - - if fileInfo.Size() != metadata.InternalKeyLen { - return nil, errors.Wrap(ErrKeyFileLength, file.Name()) - } - return crypto.NewFixedLengthKeyFromReader(file, metadata.InternalKeyLen) + return makeRawKey(info) default: return nil, ErrInvalidSource |