Skip to content

Commit

Permalink
Merge 16bfa32 into 6312365
Browse files Browse the repository at this point in the history
  • Loading branch information
ebiggers committed Mar 18, 2020
2 parents 6312365 + 16bfa32 commit 6e17b19
Show file tree
Hide file tree
Showing 22 changed files with 342 additions and 243 deletions.
145 changes: 82 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ To check whether the needed option is enabled in your kernel, run:
zgrep -h ENCRYPTION /proc/config.gz /boot/config-$(uname -r) | sort | uniq
```

It is also recommended for the kernel to be v5.4 or later, since this
allows the use of v2 encryption policies. v2 policies have several
security and usability improvements over v1 policies.

Be careful when using encryption on removable media, since filesystems with the
`encrypt` feature cannot be mounted on systems with kernel versions older than
the minimums listed above -- even to access unencrypted files!
Expand All @@ -195,12 +199,11 @@ that looks like the following:
"memory": "131072",
"parallelism": "32"
},
"compatibility": "legacy",
"options": {
"padding": "32",
"contents": "AES_256_XTS",
"filenames": "AES_256_CTS",
"policy_version": "1"
"policy_version": "2"
},
"use_fs_keyring_for_v1_policies": false
}
Expand All @@ -216,9 +219,6 @@ The fields are:
and take about 1 second. The `--time` option to `fscrypt setup` can
be used to customize this time when creating the configuration file.

* "compatibility" can be "legacy" to support kernels older than v4.8,
or the empty string to only support kernels v4.8 and later.

* "options" are the encryption options to use for new encrypted
directories:

Expand All @@ -245,9 +245,10 @@ The fields are:
for more details about the supported algorithms.

* "policy\_version" is the version of encryption policy to use.
The choices are "1" and "2". Directories created with policy
version "2" are only usable on kernel v5.4 or later, but are
preferable to version "1" if you don't mind this restriction.
The choices are "1" and "2". If unset, "1" is assumed.
Directories created with policy version "2" are only usable on
kernel v5.4 or later, but are preferable to version "1" if you
don't mind this restriction.

* "use\_fs\_keyring\_for\_v1\_policies" specifies whether to add keys
for v1 encryption policies to the filesystem keyring, rather than to
Expand Down Expand Up @@ -339,6 +340,7 @@ MOUNTPOINT DEVICE FILESYSTEM ENCRYPTION FSCRYPT

# Create the global configuration file. Nothing else necessarily needs root.
>>>>> sudo fscrypt setup
Defaulting to policy_version 2 because kernel supports it.
Customizing passphrase hashing difficulty for this system...
Created global config file at "/etc/fscrypt.conf".
Metadata directories created at "/.fscrypt".
Expand Down Expand Up @@ -367,8 +369,8 @@ ext4 filesystem "/mnt/disk" has 1 protector and 1 policy
PROTECTOR LINKED DESCRIPTION
7626382168311a9d No custom protector "Super Secret"

POLICY UNLOCKED PROTECTORS
7626382168311a9d Yes 7626382168311a9d
POLICY UNLOCKED PROTECTORS
16382f282d7b29ee27e6460151d03382 Yes 7626382168311a9d
```

#### Quiet Version
Expand All @@ -386,24 +388,23 @@ POLICY UNLOCKED PROTECTORS
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: Yes

Protected with 1 protector:
PROTECTOR LINKED DESCRIPTION
7626382168311a9d No custom protector "Super Secret"

# Lock the directory. 'sudo' and the '--user' argument are only
# required if the directory uses a v1 encryption policy.
>>>>> sudo fscrypt lock /mnt/disk/dir1 --user=$USER
Encrypted data removed from filesystem cache.
# Lock the directory. Note: if using a v1 encryption policy instead
# of v2, you'll need 'sudo fscrypt lock /mnt/disk/dir1 --user=$USER'.
>>>>> fscrypt lock /mnt/disk/dir1
"/mnt/disk/dir1" is now locked.
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: No

Protected with 1 protector:
Expand All @@ -423,8 +424,8 @@ Enter custom passphrase for protector "Super Secret":
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: Yes

Protected with 1 protector:
Expand All @@ -436,7 +437,7 @@ Hello World

#### Quiet Version
```bash
>>>>> sudo fscrypt lock /mnt/disk/dir1 --quiet --user=$USER
>>>>> fscrypt lock /mnt/disk/dir1 --quiet
>>>>> echo "hunter2" | fscrypt unlock /mnt/disk/dir1 --quiet
```

Expand All @@ -459,8 +460,8 @@ Enter login passphrase for joerichey:
>>>>> fscrypt status /mnt/disk/dir2
"/mnt/disk/dir2" is encrypted with fscrypt.

Policy: fe1c92009abc1cff
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: fe1c92009abc1cff4f3257c77e8134e3
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: Yes

Protected with 1 protector:
Expand All @@ -473,9 +474,9 @@ PROTECTOR LINKED DESCRIPTION
7626382168311a9d No custom protector "Super Secret"
6891f0a901f0065e Yes (/) login protector for joerichey

POLICY UNLOCKED PROTECTORS
16382f282d7b29ee Yes 7626382168311a9d
fe1c92009abc1cff Yes 6891f0a901f0065e
POLICY UNLOCKED PROTECTORS
16382f282d7b29ee27e6460151d03382 Yes 7626382168311a9d
fe1c92009abc1cff4f3257c77e8134e3 Yes 6891f0a901f0065e
>>>>> fscrypt status /
ext4 filesystem "/" has 1 protector(s) and 0 policy(ies)

Expand All @@ -495,8 +496,8 @@ PROTECTOR LINKED DESCRIPTION
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: Yes

Protected with 1 protector:
Expand Down Expand Up @@ -550,9 +551,9 @@ PROTECTOR LINKED DESCRIPTION
2c75f519b9c9959d No raw key protector "Skeleton"
6891f0a901f0065e Yes (/) login protector for joerichey

POLICY UNLOCKED PROTECTORS
16382f282d7b29ee Yes 7626382168311a9d
fe1c92009abc1cff Yes 6891f0a901f0065e
POLICY UNLOCKED PROTECTORS
16382f282d7b29ee27e6460151d03382 Yes 7626382168311a9d
fe1c92009abc1cff4f3257c77e8134e3 Yes 6891f0a901f0065e

# Finally, we could apply this key to a directory
>>>>> mkdir /mnt/disk/dir3
Expand Down Expand Up @@ -584,31 +585,31 @@ PROTECTOR LINKED DESCRIPTION
2c75f519b9c9959d No raw key protector "Skeleton"
6891f0a901f0065e Yes (/) login protector for joerichey

POLICY UNLOCKED PROTECTORS
d03fb894584a4318 No 2c75f519b9c9959d
16382f282d7b29ee No 7626382168311a9d
fe1c92009abc1cff No 6891f0a901f0065e
POLICY UNLOCKED PROTECTORS
d03fb894584a4318d1780e9a7b0b47eb No 2c75f519b9c9959d
16382f282d7b29ee27e6460151d03382 No 7626382168311a9d
fe1c92009abc1cff4f3257c77e8134e3 No 6891f0a901f0065e
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: No

Protected with 1 protector:
PROTECTOR LINKED DESCRIPTION
7626382168311a9d No custom protector "Super Secret"
>>>>> fscrypt metadata add-protector-to-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee
>>>>> fscrypt metadata add-protector-to-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee27e6460151d03382
WARNING: All files using this policy will be accessible with this protector!!
Protect policy 16382f282d7b29ee with protector 2c75f519b9c9959d? [Y/n]
Protect policy 16382f282d7b29ee27e6460151d03382 with protector 2c75f519b9c9959d? [Y/n]
Enter key file for protector "Skeleton": secret.key
Enter custom passphrase for protector "Super Secret":
Protector 2c75f519b9c9959d now protecting policy 16382f282d7b29ee.
Protector 2c75f519b9c9959d now protecting policy 16382f282d7b29ee27e6460151d03382.
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

Policy: 16382f282d7b29ee
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:1
Policy: 16382f282d7b29ee27e6460151d03382
Options: padding:32 contents:AES_256_XTS filenames:AES_256_CTS policy_version:2
Unlocked: No

Protected with 2 protectors:
Expand All @@ -626,16 +627,16 @@ Enter key file for protector "Skeleton": secret.key
"/mnt/disk/dir1" is now unlocked and ready for use.

# The protector can also be removed from the policy (if it is not the only one)
>>>>> fscrypt metadata remove-protector-from-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee
>>>>> fscrypt metadata remove-protector-from-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee27e6460151d03382
WARNING: All files using this policy will NO LONGER be accessible with this protector!!
Stop protecting policy 16382f282d7b29ee with protector 2c75f519b9c9959d? [y/N] y
Protector 2c75f519b9c9959d no longer protecting policy 16382f282d7b29ee.
Stop protecting policy 16382f282d7b29ee27e6460151d03382 with protector 2c75f519b9c9959d? [y/N] y
Protector 2c75f519b9c9959d no longer protecting policy 16382f282d7b29ee27e6460151d03382.
```

#### Quiet Version
```bash
>>>>> echo "hunter2" | fscrypt metadata add-protector-to-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee --key=secret.key --quiet
>>>>> fscrypt metadata remove-protector-from-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee --quiet --force
>>>>> echo "hunter2" | fscrypt metadata add-protector-to-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee27e6460151d03382 --key=secret.key --quiet
>>>>> fscrypt metadata remove-protector-from-policy --protector=/mnt/disk:2c75f519b9c9959d --policy=/mnt/disk:16382f282d7b29ee27e6460151d03382 --quiet --force
```

## Contributing
Expand Down Expand Up @@ -750,27 +751,45 @@ manifest in other ways such as Docker containers being unable to
access encrypted files, or NetworkManager being unable to access
certificates if they are located in an encrypted directory.

If you are using kernel v5.4 or later, you can fix this by setting the
following in `/etc/fscrypt.conf`:
The recommended way to fix this is by creating your encrypted
directories using v2 encryption policies rather than v1. This
requires Linux v5.4 or later and `fscrypt` v0.2.6 or later. If these
prerequisites are met, to enable v2 policies on new directories set
`"policy_version": "2"` in `/etc/fscrypt.conf`. For example:

"use_fs_keyring_for_v1_policies": true
```
"options": {
"padding": "32",
"contents": "AES_256_XTS",
"filenames": "AES_256_CTS",
"policy_version": "2"
},
```

This only affects new directories. If you want to upgrade an existing
encrypted directory to use a v2 policy, you'll need to re-create it by
using `fscrypt encrypt` to encrypt a new empty directory, copying your
files into it, and replacing the original directory with it.

However, this makes manually unlocking and locking encrypted
directories start to require root. (The PAM module will still work.)
E.g., you'll need to run `sudo fscrypt unlock`, not `fscrypt unlock`.
In `fscrypt` v0.2.7 and later, the `fscrypt setup` command
automatically sets `"policy_version": "2"` when creating
`/etc/fscrypt.conf` if kernel support is present.

Alternatively, you can upgrade your encrypted directories to use v2
encryption policies by setting the following in the "options" section
of `/etc/fscrypt.conf`:
__IMPORTANT:__ directories that use v2 encryption policies are
unusable on Linux v5.3 and earlier. If this will be a problem for you
(for example, if your encrypted directories are on removable storage
that needs to work on computers with both old and new kernels), you'll
need to use v1 policies instead. In this case, or if you simply don't
want to re-create your encrypted directories, there's also a fallback
option to make `fscrypt` use the filesystem keyring for v1 policies
whenever the kernel supports it:

"policy_version": "2"
"use_fs_keyring_for_v1_policies": true

... and then for each of your encrypted directories, using `fscrypt
encrypt` to encrypt a new empty directory, copying your files into it,
and replacing the original directory with it. This will fix the key
access problems, while also keeping `fscrypt unlock` and `fscrypt
lock` usable by non-root users. This is the recommended solution if
you don't need to access your files on kernels older than v5.4.
However, this fallback option makes manually unlocking and locking
encrypted directories start to require root. (The PAM module will
still work.) E.g., you'll need to run `sudo fscrypt unlock`, not
`fscrypt unlock`. Most people should just use v2 policies instead.

## Legal

Expand Down
20 changes: 7 additions & 13 deletions actions/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ import (
"github.com/google/fscrypt/util"
)

// LegacyConfig indicates that keys should be inserted into the keyring with the
// legacy service prefixes. Needed for kernels before v4.8.
const LegacyConfig = "legacy"

// ConfigFileLocation is the location of fscrypt's global settings. This can be
// overridden by the user of this package.
var ConfigFileLocation = "/etc/fscrypt.conf"
Expand All @@ -61,12 +57,10 @@ var (
)

// CreateConfigFile creates a new config file at the appropriate location with
// the appropriate hashing costs and encryption parameters. This creation is
// configurable in two ways. First, a time target must be specified. This target
// will determine the hashing costs, by picking parameters that make the hashing
// take as long as the specified target. Second, the config can include the
// legacy option, which is needed for systems with kernels older than v4.8.
func CreateConfigFile(target time.Duration, useLegacy bool) error {
// the appropriate hashing costs and encryption parameters. The hashing will be
// configured to take as long as the specified time target. In addition, the
// version of encryption policy to use may be overridden from the default of v1.
func CreateConfigFile(target time.Duration, policyVersion int64) error {
// Create the config file before computing the hashing costs, so we fail
// immediately if the program has insufficient permissions.
configFile, err := filesystem.OpenFileOverridingUmask(ConfigFileLocation,
Expand All @@ -83,9 +77,9 @@ func CreateConfigFile(target time.Duration, useLegacy bool) error {
Source: metadata.DefaultSource,
Options: metadata.DefaultOptions,
}
if useLegacy {
config.Compatibility = LegacyConfig
log.Printf("Using %q compatibility option\n", LegacyConfig)

if policyVersion != 0 {
config.Options.PolicyVersion = policyVersion
}

if config.HashCosts, err = getHashingCosts(target); err != nil {
Expand Down
26 changes: 25 additions & 1 deletion actions/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"time"

"golang.org/x/sys/unix"

"github.com/google/fscrypt/metadata"
)

// Test that the global config file is created with mode 0644, regardless of the
Expand All @@ -42,7 +44,7 @@ func TestConfigFileIsCreatedWithCorrectMode(t *testing.T) {
defer os.RemoveAll(tempDir)
ConfigFileLocation = filepath.Join(tempDir, "test.conf")

if err = CreateConfigFile(time.Millisecond, false); err != nil {
if err = CreateConfigFile(time.Millisecond, 0); err != nil {
t.Fatal(err)
}
fileInfo, err := os.Stat(ConfigFileLocation)
Expand All @@ -53,3 +55,25 @@ func TestConfigFileIsCreatedWithCorrectMode(t *testing.T) {
t.Error("Expected newly created config file to have mode 0644")
}
}

func TestCreateConfigFileV2Policy(t *testing.T) {
tempDir, err := ioutil.TempDir("", "fscrypt")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tempDir)
ConfigFileLocation = filepath.Join(tempDir, "test.conf")

if err = CreateConfigFile(time.Millisecond, 2); err != nil {
t.Fatal(err)
}

var config *metadata.Config
config, err = getConfig()
if err != nil {
t.Fatal(err)
}
if config.Options.PolicyVersion != 2 {
t.Error("Expected PolicyVersion 2")
}
}
Loading

0 comments on commit 6e17b19

Please sign in to comment.