Git Product home page Git Product logo

fscrypt's Introduction

fscrypt GitHub version

Build Status GoDoc Go Report Card License

fscrypt is a high-level tool for the management of Linux native filesystem encryption. fscrypt manages metadata, key generation, key wrapping, PAM integration, and provides a uniform interface for creating and modifying encrypted directories. For a small low-level tool that directly sets policies, see fscryptctl.

To use fscrypt, you must have a filesystem that supports the Linux native filesystem encryption API (which is also sometimes called "fscrypt"; this documentation calls it "Linux native filesystem encryption" to avoid confusion). Only certain filesystems, such as ext4 and f2fs, support this API. For a full list of supported filesystems and how to enable encryption support on each one, see Runtime dependencies.

For the release notes, see the NEWS file.

Table of contents

Alternatives to consider

Operating-system level storage encryption solutions work at either the filesystem or block device level. Linux native filesystem encryption (the solution configured by fscrypt) is filesystem-level; it encrypts individual directories. Only file contents and filenames are encrypted; non-filename metadata, such as timestamps, the sizes and number of files, and extended attributes, is not encrypted. Users choose which directories will be encrypted, and with what keys.

Before using fscrypt, you should consider other solutions:

  • dm-crypt/LUKS is block device level encryption: it encrypts an entire block device (and hence an entire filesystem) with one key. Unlocking this key will unlock the entire block device. dm-crypt/LUKS is usually configured using cryptsetup.

  • systemd-homed supports encrypting home directories using the same Linux native filesystem encryption API that fscrypt uses. Note that while the systemd-homed documentation refers to this as fscrypt support, it does not use the fscrypt tool; directories set up using systemd-homed cannot be managed by fscrypt and vice versa. systemd-homed has better integration with systemd than fscrypt does; however, systemd-homed (as of systemd v255) uses an obsolete version of the Linux native filesystem encryption API, and users may run into known issues. Issues with systemd-homed should be reported to the systemd developers.

  • eCryptfs is an alternative filesystem-level encryption solution. It is a stacked filesystem, which means it sits on top of a real filesystem, rather than being directly integrated into the real filesystem. Stacked filesystems have a couple advantages (such as working on almost any real filesystem), but also some significant disadvantages. eCryptfs is usually configured using ecryptfs-utils.

  • Some Linux filesystems support encryption natively, but not in a way that is compatible with the common API that fscrypt uses. Examples of this are Bcachefs and ZFS. (Note: ZFS is not part of the upstream kernel.) Bcachefs encryption is similar to dm-crypt in that it encrypts the full filesystem with one key. ZFS encryption operates on a per-dataset basis. If you are using one of these filesystems, refer to the documentation for that filesystem.

Which solution to use? Here are our recommendations:

  • eCryptfs shouldn't be used, if at all possible. eCryptfs's use of filesystem stacking causes a number of issues, and eCryptfs is no longer actively maintained. The original author of eCryptfs recommends using Linux native filesystem encryption instead. The largest users of eCryptfs (Ubuntu and Chrome OS) have switched to dm-crypt or Linux native filesystem encryption.

  • If you need fine-grained control of encryption within a filesystem and you are using a filesystem that supports fscrypt, then use fscrypt, or fscrypt together with dm-crypt/LUKS. If you don't need this, then use dm-crypt/LUKS.

    To understand this recommendation: consider that the main advantage of fscrypt is to allow different files on the same filesystem to be encrypted by different keys, and thus be unlockable, lockable, and securely deletable independently from each other. Therefore, fscrypt is useful in cases such as:

    • Multi-user systems, since each user's files can be encrypted with their own key that is unlocked by their own passphrase.

    • Single-user systems where it's not possible for all files to have the strongest level of protection. For example, it might be necessary for the system to boot up without user interaction. Any files that are needed to do so can only be encrypted by a hardware-protected (e.g. TPM-bound) key at best. If the user's personal files are located on the same filesystem, then with dm-crypt/LUKS the user's personal files would be limited to this weak level of protection. With fscrypt, the user's personal files could be fully protected using the user's passphrase.

    fscrypt isn't very useful in the following cases:

    • Single-user systems where the user is willing to enter a strong passphrase at boot time to unlock the entire filesystem. In this case, the main advantage of fscrypt would go unused, so dm-crypt/LUKS would be better as it would provide better security (due to ensuring that all files and all filesystem metadata are encrypted).

    • Any case where it is feasible to create a separate filesystem for every encryption key you want to use.

    Note: dm-crypt/LUKS and fscrypt aren't mutually exclusive; they can be used together when the performance hit of double encryption is tolerable. It only makes sense to do this when the keys for each encryption layer are protected in different ways, such that each layer serves a different purpose. A reasonable set-up would be to encrypt the whole filesystem with dm-crypt/LUKS using a TPM-bound key that is automatically unlocked at boot time, and also encrypt users' home directories with fscrypt using their login passphrases.

Threat model

Like other storage encryption solutions (including dm-crypt/LUKS and eCryptfs), Linux native filesystem encryption is primarily intended to protect the confidentiality of data from a single point-in-time permanent offline compromise of the disk. For a detailed description of the threat model, see the kernel documentation.

It's worth emphasizing that none of these encryption solutions protect unlocked encrypted files from other users on the same system (that's the job of OS-level access control, such as UNIX file permissions), or from the cloud provider you may be running a virtual machine on. By themselves, they also do not protect from "evil maid" attacks, i.e. non-permanent offline compromises of the disk.

Features

fscrypt is intended to improve upon the work in e4crypt by providing a more managed environment and handling more functionality in the background. fscrypt has a design document specifying its full architecture. See also the kernel documentation for Linux native filesystem encryption.

Briefly, fscrypt deals with protectors and policies. Protectors represent some secret or information used to protect the confidentiality of your data. The three currently supported protector types are:

  1. Your login passphrase, through PAM. The included PAM module (pam_fscrypt.so) can automatically unlock directories protected by your login passphrase when you log in, and lock them when you log out. IMPORTANT: before using a login protector, follow Setting up for login protectors.

  2. A custom passphrase. This passphrase is hashed with Argon2id, by default calibrated to use all CPUs and take about 1 second.

  3. A raw key file. See Using a raw key protector.

These protectors are mutable, so the information can change without needing to update any of your encrypted directories.

Policies represent the actual key passed to the kernel. This "policy key" is immutable and policies are (usually) applied to a single directory. Protectors then protect policies, so that having one of the protectors for a policy is enough to get the policy key and access the data. Which protectors protect a policy can also be changed. This allows a user to change how a directory is protected without needing to reencrypt the directory's contents.

Concretely, fscrypt contains the following functionality:

  • fscrypt setup - Creates /etc/fscrypt.conf and the /.fscrypt directory
    • This is the only functionality which always requires root privileges
  • fscrypt setup MOUNTPOINT - Gets a filesystem ready for use with fscrypt
  • fscrypt encrypt DIRECTORY - Encrypts an empty directory
  • fscrypt unlock DIRECTORY - Unlocks an encrypted directory
  • fscrypt lock DIRECTORY - Locks an encrypted directory
  • fscrypt purge MOUNTPOINT - Locks all encrypted directories on a filesystem
  • fscrypt status [PATH] - Gets detailed info about filesystems or paths
  • fscrypt metadata - Manages policies or protectors directly

See the example usage section below or run fscrypt COMMAND --help for more information about each of the commands.

Building and installing

fscrypt has a minimal set of build dependencies:

  • Go 1.18 or higher. Older versions may work but they are not tested or supported.
  • A C compiler (gcc or clang)
  • make
  • Headers for libpam. Install them with the appropriate package manager:
    • Debian/Ubuntu: sudo apt install libpam0g-dev
    • Red Hat: sudo yum install pam-devel
    • Arch: pam package (usually installed by default)

Once all the dependencies are installed, clone the repository by running:

git clone https://github.com/google/fscrypt

Running make builds the binary (fscrypt) and PAM module (pam_fscrypt.so) in the bin/ directory.

Running sudo make install installs fscrypt into /usr/local/bin, pam_fscrypt.so into /usr/local/lib/security, and pam_fscrypt/config into /usr/local/share/pam-configs.

On Debian (and Debian derivatives such as Ubuntu), use sudo make install PREFIX=/usr to install into /usr instead of the default of /usr/local. Ordinarily you shouldn't manually install software into /usr, since /usr is reserved for Debian's own packages. However, Debian's PAM configuration framework only recognizes configuration files in /usr, not in /usr/local. Therefore, the PAM module will only work if you install into /usr. Note: if you later decide to switch to using the Debian package libpam-fscrypt, you'll have to first manually run sudo make uninstall PREFIX=/usr.

It is also possible to use make install-bin to only install the fscrypt binary, or make install-pam to only install the PAM files.

Alternatively, if you only want to install the fscrypt binary to $GOPATH/bin, simply run:

go install github.com/google/fscrypt/cmd/fscrypt@latest

See the Makefile for instructions on how to further customize the build.

Runtime dependencies

To run, fscrypt needs the following libraries:

  • libpam.so (almost certainly already on your system)

In addition, fscrypt requires a filesystem that supports the Linux native filesystem encryption API. Currently, the filesystems that support this are:

  • ext4, with upstream kernel v4.1 or later. The kernel configuration must contain CONFIG_FS_ENCRYPTION=y (for kernels v5.1+) or CONFIG_EXT4_ENCRYPTION=y or =m (for older kernels). The filesystem must also have the encrypt feature flag enabled; to enable this flag, see here.

  • f2fs, with upstream kernel v4.2 or later. The kernel configuration must contain CONFIG_FS_ENCRYPTION=y (for kernels v5.1+) or CONFIG_F2FS_FS_ENCRYPTION=y (for older kernels). The filesystem must also have the encrypt feature flag enabled; this flag can be enabled at format time by mkfs.f2fs -O encrypt or later by fsck.f2fs -O encrypt.

  • UBIFS, with upstream kernel v4.10 or later. The kernel configuration must contain CONFIG_FS_ENCRYPTION=y (for kernels v5.1+) or CONFIG_UBIFS_FS_ENCRYPTION=y (for older kernels).

  • CephFS, with upstream kernel v6.6 or later. The kernel configuration must contain CONFIG_FS_ENCRYPTION=y.

  • Lustre, with Lustre v2.14.0 or later. For details, see the Lustre documentation. Please note that Lustre is not part of the upstream Linux kernel, and its encryption implementation has not been reviewed by the authors of fscrypt. Questions/issues about Lustre encryption should be directed to the Lustre developers. Lustre version 2.14 does not encrypt filenames, even though it claims to, so v2.15.0 or later should be used.

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 to use Linux kernel v5.4 or later, since this allows the use of v2 encryption policies. v2 policies have several security and usability improvements over v1 policies.

If you configure fscrypt to use non-default features, other kernel prerequisites may be needed too. See Configuration file.

Configuration file

Running sudo fscrypt setup will create the configuration file /etc/fscrypt.conf if it doesn't already exist. It's a JSON file that looks like the following:

{
	"source": "custom_passphrase",
	"hash_costs": {
		"time": "52",
		"memory": "131072",
		"parallelism": "32"
	},
	"options": {
		"padding": "32",
		"contents": "AES_256_XTS",
		"filenames": "AES_256_CTS",
		"policy_version": "2"
	},
	"use_fs_keyring_for_v1_policies": false,
	"allow_cross_user_metadata": false
}

The fields are:

  • "source" is the default source for new protectors. The choices are "pam_passphrase", "custom_passphrase", and "raw_key".

  • "hash_costs" describes how difficult the passphrase hashing is. By default, fscrypt setup calibrates the hashing to use all CPUs and take about 1 second. The --time option to fscrypt setup can be used to customize this time when creating the configuration file.

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

    • "padding" is the number of bytes by which filenames are padded before being encrypted. The choices are "32", "16", "8", and "4". "32" is recommended.

    • "contents" is the algorithm used to encrypt file contents. The choices are "AES_256_XTS", "AES_128_CBC", and "Adiantum". Normally, "AES_256_XTS" is recommended.

    • "filenames" is the algorithm used to encrypt file names. The choices are "AES_256_CTS", "AES_128_CTS", "Adiantum", and "AES_256_HCTR2". Normally, "AES_256_CTS" is recommended.

      To use algorithms other than "AES_256_XTS" for contents and "AES_256_CTS" for filenames, the needed algorithm(s) may need to be enabled in the Linux kernel's cryptography API. For example, to use Adiantum, CONFIG_CRYPTO_ADIANTUM must be set. Also, not all combinations of algorithms are allowed; for example, "Adiantum" for contents can only be paired with "Adiantum" for filenames. See the kernel documentation for more details about the supported algorithms.

    • "policy_version" is the version of encryption policy to use. 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 keyrings, rather than to user keyrings. This can solve issues with processes being unable to access unlocked encrypted files. However, it requires kernel v5.4 or later, and it makes unlocking and locking encrypted directories require root. (The PAM module will still work.)

    The purpose of this setting is to allow people to take advantage of some of the improvements in Linux v5.4 on encrypted directories that are also compatible with older kernels. If you don't need compatibility with older kernels, it's better to not use this setting and instead (re-)create your encrypted directories with "policy_version": "2".

  • "allow_cross_user_metadata" specifies whether fscrypt will allow protectors and policies from other non-root users to be read, e.g. to be offered as options by fscrypt encrypt. The default value is false, since other users might be untrusted and could create malicious files. This can be set to true to restore the old behavior on systems where fscrypt metadata needs to be shared between multiple users. Note that this option is independent from the permissions on the metadata files themselves, which are set to 0600 by default; users who wish to share their metadata files with other users would also need to explicitly change their mode to 0644.

Setting up fscrypt on a filesystem

fscrypt needs some directories to exist on the filesystem on which encryption will be used:

  • MOUNTPOINT/.fscrypt/policies
  • MOUNTPOINT/.fscrypt/protectors

(If login protectors are used, these must also exist on the root filesystem.)

To create these directories, run fscrypt setup MOUNTPOINT. If MOUNTPOINT is owned by root, as is usually the case, then this command will require root.

There will be one decision you'll need to make: whether non-root users will be allowed to create fscrypt metadata (policies and protectors).

If you say y, then these directories will be made world-writable, with the sticky bit set so that users can't delete each other's files -- just like /tmp. If you say N, then these directories will be writable only by root.

Saying y maximizes the usability of fscrypt, and on most systems it's fine to say y. However, on some systems this may be inappropriate, as it will allow malicious users to fill the entire filesystem unless filesystem quotas have been configured -- similar to problems that have historically existed with other world-writable directories, e.g. /tmp. If you are concerned about this, say N. If you say N, then you'll only be able to run fscrypt as root to set up encryption on users' behalf, unless you manually set custom permissions on the metadata directories to grant write access to specific users or groups.

If you chose the wrong mode at fscrypt setup time, you can change the directory permissions at any time. To enable single-user writable mode, run:

sudo chmod 0755 MOUNTPOINT/.fscrypt/*

To enable world-writable mode, run:

sudo chmod 1777 MOUNTPOINT/.fscrypt/*

Setting up for login protectors

If you want any encrypted directories to be protected by your login passphrase, you'll need to:

  1. Secure your login passphrase (optional, but strongly recommended)
  2. Enable the PAM module (pam_fscrypt.so)

If you installed fscrypt from source rather than from your distro's package manager, you may also need to allow fscrypt to check your login passphrase.

Securing your login passphrase

Although fscrypt uses a strong passphrase hash algorithm, the security of login protectors is also limited by the strength of your system's passphrase hashing in /etc/shadow. On most Linux distributions, /etc/shadow by default uses SHA-512 with 5000 rounds, which is much weaker than what fscrypt uses.

To mitigate this, you should use a strong login passphrase.

If using a strong login passphrase is annoying because it needs to be entered frequently to run sudo, consider increasing the sudo timeout. That can be done by adding the following to /etc/sudoers:

Defaults timestamp_timeout=60

You should also increase the number of rounds that your system's passphrase hashing uses (though this doesn't increase security as much as choosing a strong passphrase). To do this, find the line in /etc/pam.d/passwd that looks like:

password	required	pam_unix.so sha512 shadow nullok

Append rounds=1000000 (or another number of your choice; the goal is to make the passphrase hashing take about 1 second, similar to fscrypt's default):

password	required	pam_unix.so sha512 shadow nullok rounds=1000000

Then, change your login passphrase to a new, strong passphrase:

passwd

If you'd like to keep the same login passphrase (not recommended, as the old passphrase hash may still be recoverable from disk), then instead run sudo passwd $USER and enter your existing passphrase. This re-hashes your existing passphrase with the new rounds.

Enabling the PAM module

To enable the PAM module pam_fscrypt.so, follow the directions for your Linux distro below. Enabling the PAM module is needed for login passphrase-protected directories to be automatically unlocked when you log in (and be automatically locked when you log out), and for login passphrase-protected directories to remain accessible when you change your login passphrase.

Enabling the PAM module on Debian or Ubuntu

The official libpam-fscrypt package for Debian (and Debian derivatives such as Ubuntu) will install a configuration file for Debian's PAM configuration framework to /usr/share/pam-configs/fscrypt. This file contains reasonable defaults for the PAM module. To automatically apply these defaults, run sudo pam-auth-update and follow the on-screen instructions.

This file also gets installed if you build and install fscrypt from source, but it is only installed to the correct location if you use make install PREFIX=/usr to install into /usr instead of the default of /usr/local.

Enabling the PAM module on Arch Linux

On Arch Linux, follow the recommendations at the Arch Linux Wiki.

We recommend using the Arch Linux package, either fscrypt (official) or fscrypt-git (AUR). If you instead install fscrypt manually using sudo make install, then in addition to the steps on the Wiki you'll also need to create /etc/pam.d/fscrypt.

Enabling the PAM module on other Linux distros

On all other Linux distros, follow the general guidance below to edit your PAM configuration files.

The fscrypt PAM module implements the Auth, Session, and Password types.

The Password functionality of pam_fscrypt.so is used to automatically rewrap a user's login protector when their unix passphrase changes. An easy way to get the working is to add the line:

password    optional    pam_fscrypt.so

after pam_unix.so in /etc/pam.d/common-password or similar.

The Auth and Session functionality of pam_fscrypt.so are used to automatically unlock directories when logging in as a user, and lock them when logging out. An easy way to get this working is to add the line:

auth        optional    pam_fscrypt.so

after pam_unix.so in /etc/pam.d/common-auth or similar, and to add the line:

session     optional    pam_fscrypt.so

after pam_unix.so in /etc/pam.d/common-session or similar, but before pam_systemd.so or any other module that accesses the user's home directory or which starts processes that access the user's home directory during their session.

pam_fscrypt.so accepts several options:

  • debug: print additional debug messages to the syslog. All hook types accept this option.

  • unlock_only: only unlock directories (at log-in); don't also lock them (at log-out). This is only relevant for the "session" hook. Note that in fscrypt v0.2.9 and earlier, unlock-only was the default behavior, and lock_policies needed to be specified to enable locking.

Allowing fscrypt to check your login passphrase

This step is only needed if you installed fscrypt from source code.

Some Linux distros use restrictive settings in /etc/pam.d/other that prevent programs from checking your login passphrase unless a per-program PAM configuration file grants access. This prevents fscrypt from creating any login passphrase-protected directories, even without auto-unlocking. To ensure that fscrypt will work properly (if you didn't install an official fscrypt package from your distro, which should have already handled this), also create a file /etc/pam.d/fscrypt containing:

auth        required    pam_unix.so

Backup, restore, and recovery

Encrypted files and directories can't be backed up while they are "locked", i.e. while they appear in encrypted form. They can only be backed up while they are unlocked, in which case they can be backed up like any other files. Note that since the encryption is transparent, the files won't be encrypted in the backup (unless the backup applies its own encryption).

For the same reason (and several others), an encrypted directory can't be directly "moved" to another filesystem. However, it is possible to create a new encrypted directory on the destination filesystem using fscrypt encrypt, then copy the contents of the source directory into it.

For directories protected by a custom_passphrase or raw_key protector, all metadata needed to unlock the directory (excluding the actual passphrase or raw key, of course) is located in the .fscrypt directory at the root of the filesystem that contains the encrypted directory. For example, if you have an encrypted directory /home/$USER/private that is protected by a custom passphrase, all fscrypt metadata needed to unlock the directory with that custom passphrase will be located in /home/.fscrypt if you are using a dedicated /home filesystem or in /.fscrypt if you aren't. If desired, you can back up the fscrypt metadata by making a copy of this directory, although this isn't too important since this metadata is located on the same filesystem as the encrypted directory(s).

pam_passphrase (login passphrase) protectors are a bit different as they are always stored on the root filesystem, in /.fscrypt. This ties them to the specific system and ensures that each user has only a single login protector. Therefore, encrypted directories on a non-root filesystem can't be unlocked via a login protector if the operating system is reinstalled or if the disk is connected to another system -- even if the new system uses the same login passphrase for the user.

Because of this, fscrypt encrypt will automatically generate a recovery passphrase when creating a login passphrase-protected directory on a non-root filesystem. The recovery passphrase is simply a custom_passphrase protector with a randomly generated high-entropy passphrase. Initially, the recovery passphrase is stored in a file in the encrypted directory itself; therefore, to use it you must record it in another secure location. It is strongly recommended to do this. Then, if ever needed, you can use fscrypt unlock to unlock the directory with the recovery passphrase (by choosing the recovery protector instead of the login protector).

If you really want to disable the generation of a recovery passphrase, use the --no-recovery option. Only do this if you really know what you are doing and are prepared for potential data loss.

Alternative approaches to supporting recovery of login passphrase-protected directories include the following:

  • Manually adding your own recovery protector, using fscrypt metadata add-protector-to-policy.

  • Backing up and restoring the /.fscrypt directory on the root filesystem. Note that after restoring the /.fscrypt directory, unlocking the login protectors will require the passphrases they had at the time the backup was made even if they were changed later, so make sure to remember these passphrase(s) or record them in a secure location. Also note that if the UUID of the root filesystem changed, you will need to manually fix the UUID in any .fscrypt/protectors/*.link files on other filesystems.

The auto-generated recovery passphrases should be enough for most users, though.

Encrypting existing files

fscrypt isn't designed to encrypt existing files, as this presents significant technical challenges and usually is impossible to do securely. Therefore, fscrypt encrypt only works on empty directories.

Of course, it is still possible to create an encrypted directory, copy files into it, and delete the original files. The mv command will even work, as it will fall back to a copy and delete (except on older kernels). However, beware that due to the characteristics of filesystems and storage devices, this may not properly protect the files, as their original contents may still be forensically recoverable from disk even after being deleted. It's much better to encrypt files from the very beginning.

There are only a few cases where copying files into an encrypted directory can really make sense, such as:

  • The source files are located on an in-memory filesystem such as tmpfs.

  • The confidentiality of the source files isn't important, e.g. they are system default files and the user hasn't added any personal files yet.

  • The source files are protected by a different fscrypt policy, the old and new policies are protected by only the same protector(s), and the old policy uses similar strength encryption.

If one of the above doesn't apply, then it's probably too late to securely encrypt your existing files.

As a best-effort attempt, you can use the shred program to try to erase the original files. Here are the recommended commands for "best-effort" encryption of an existing directory named "dir":

mkdir dir.new
fscrypt encrypt dir.new
cp -a -T dir dir.new
find dir -type f -print0 | xargs -0 shred -n1 --remove=unlink
rm -rf dir
mv dir.new dir

However, beware that shred isn't guaranteed to be effective on all storage devices and filesystems. For example, if you're using an SSD, "overwrites" of data typically go to new flash blocks, so they aren't really overwrites.

Note: for reasons similar to the above, changed or removed fscrypt protectors aren't guaranteed to be forensically unrecoverable from disk either. Thus, the use of weak or default passphrases should be avoided, even if changed later.

Example usage

All these examples assume there is an ext4 filesystem which supports encryption mounted at /mnt/disk. See here for how to enable encryption support on an ext4 filesystem.

Setting up fscrypt on a directory

# Check which directories on our system support encryption
>>>>> fscrypt status
filesystems supporting encryption: 1
filesystems with fscrypt metadata: 0

MOUNTPOINT  DEVICE     FILESYSTEM  ENCRYPTION   FSCRYPT
/           /dev/sda1  ext4        not enabled  No
/mnt/disk   /dev/sdb   ext4        supported    No

# 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".
Allow users other than root to create fscrypt metadata on the root filesystem?
(See https://github.com/google/fscrypt#setting-up-fscrypt-on-a-filesystem) [y/N] y
Metadata directories created at "/.fscrypt", writable by everyone.

# Start using fscrypt with our filesystem
>>>>> sudo fscrypt setup /mnt/disk
Allow users other than root to create fscrypt metadata on this filesystem? (See
https://github.com/google/fscrypt#setting-up-fscrypt-on-a-filesystem) [y/N] y
Metadata directories created at "/mnt/disk/.fscrypt", writable by everyone.

# Initialize encryption on a new empty directory
>>>>> mkdir /mnt/disk/dir1
>>>>> fscrypt encrypt /mnt/disk/dir1
The following protector sources are available:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 2
Enter a name for the new protector: Super Secret
Enter custom passphrase for protector "Super Secret":
Confirm passphrase:
"/mnt/disk/dir1" is now encrypted, unlocked, and ready for use.

# We can see this created one policy and one protector for this directory
>>>>> fscrypt status /mnt/disk
ext4 filesystem "/mnt/disk" has 1 protector and 1 policy

PROTECTOR         LINKED  DESCRIPTION
7626382168311a9d  No      custom protector "Super Secret"

POLICY                            UNLOCKED  PROTECTORS
16382f282d7b29ee27e6460151d03382  Yes       7626382168311a9d

Quiet version

>>>>> sudo fscrypt setup --quiet --force --all-users
>>>>> sudo fscrypt setup /mnt/disk --quiet --all-users
>>>>> echo "hunter2" | fscrypt encrypt /mnt/disk/dir1 --quiet --source=custom_passphrase  --name="Super Secret"

Locking and unlocking a directory

# Write a file to our encrypted directory.
>>>>> echo "Hello World" > /mnt/disk/dir1/secret.txt
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

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.  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:   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"

# Now the filenames and file contents are inaccessible
>>>>> ls /mnt/disk/dir1
u,k20l9HrtrizDjh0zGkw2dTfBkX4T0ZDUlsOhBLl4P
>>>>> cat /mnt/disk/dir1/u,k20l9HrtrizDjh0zGkw2dTfBkX4T0ZDUlsOhBLl4P
cat: /mnt/disk/dir1/u,k20l9HrtrizDjh0zGkw2dTfBkX4T0ZDUlsOhBLl4P: Required key not available

# Unlocking the directory makes the contents available
>>>>> fscrypt unlock /mnt/disk/dir1
Enter custom passphrase for protector "Super Secret":
"/mnt/disk/dir1" is now unlocked and ready for use.
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

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"
>>>>> cat /mnt/disk/dir1/secret.txt
Hello World

Quiet version

>>>>> fscrypt lock /mnt/disk/dir1 --quiet
>>>>> echo "hunter2" | fscrypt unlock /mnt/disk/dir1 --quiet

Protecting a directory with your login passphrase

First, ensure that you have properly set up your system for login protectors.

Then, you can protect directories with your login passphrase as follows:

# Select your login passphrase as the desired source.
>>>>> mkdir /mnt/disk/dir2
>>>>> fscrypt encrypt /mnt/disk/dir2
Should we create a new protector? [y/N] y
The following protector sources are available:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 1
Enter login passphrase for joerichey:
"/mnt/disk/dir2" is now encrypted, unlocked, and ready for use.

# Note that the login protector actually sits on the root filesystem
>>>>> fscrypt status /mnt/disk/dir2
"/mnt/disk/dir2" is encrypted with fscrypt.

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

Protected with 1 protector:
PROTECTOR         LINKED   DESCRIPTION
6891f0a901f0065e  Yes (/)  login protector for joerichey
>>>>> fscrypt status /mnt/disk
ext4 filesystem "/mnt/disk" has 2 protectors and 2 policies

PROTECTOR         LINKED   DESCRIPTION
7626382168311a9d  No       custom protector "Super Secret"
6891f0a901f0065e  Yes (/)  login protector for joerichey

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

PROTECTOR         LINKED  DESCRIPTION
6891f0a901f0065e  No      login protector for joerichey

Quiet version

>>>>> mkdir /mnt/disk/dir2
>>>>> echo "password" | fscrypt encrypt /mnt/disk/dir2 --source=pam_passphrase --quiet

Changing a custom passphrase

# First we have to figure out which protector we wish to change.
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

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"

# Now specify the protector directly to the metadata command
>>>>> fscrypt metadata change-passphrase --protector=/mnt/disk:7626382168311a9d
Enter old custom passphrase for protector "Super Secret":
Enter new custom passphrase for protector "Super Secret":
Confirm passphrase:
Passphrase for protector 7626382168311a9d successfully changed.

Quiet version

>>>>> printf "hunter2\nhunter3" | fscrypt metadata change-passphrase --protector=/mnt/disk:7626382168311a9d --quiet

Using a raw key protector

fscrypt also supports protectors which use raw key files as the user-provided secret. These key files must be exactly 32 bytes long and contain the raw binary data of the key. Obviously, make sure to store the key file securely (and not in the directory you are encrypting with it). If generating the keys on Linux make sure you are aware of how randomness works and some common myths.

# Generate a 256-bit key file
>>>>> head --bytes=32 /dev/urandom > secret.key

# Now create a key file protector without using it on a directory. Note that we
# could also use `fscrypt encrypt --key=secret.key` to achieve the same thing.
>>>>> fscrypt metadata create protector /mnt/disk
Create new protector on "/mnt/disk" [Y/n] y
The following protector sources are available:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 3
Enter a name for the new protector: Skeleton
Enter key file for protector "Skeleton": secret.key
Protector 2c75f519b9c9959d created on filesystem "/mnt/disk".
>>>>> fscrypt status /mnt/disk
ext4 filesystem "/mnt/disk" has 3 protectors and 2 policies

PROTECTOR         LINKED   DESCRIPTION
7626382168311a9d  No       custom protector "Super Secret"
2c75f519b9c9959d  No       raw key protector "Skeleton"
6891f0a901f0065e  Yes (/)  login protector for joerichey

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

# Finally, we could apply this key to a directory
>>>>> mkdir /mnt/disk/dir3
>>>>> fscrypt encrypt /mnt/disk/dir3 --protector=/mnt/disk:2c75f519b9c9959d
Enter key file for protector "Skeleton": secret.key
"/mnt/disk/dir3" is now encrypted, unlocked, and ready for use.

Quiet version

>>>>> head --bytes=32 /dev/urandom > secret.key
>>>>> fscrypt encrypt /mnt/disk/dir3 --key=secret.key --source=raw_key --name=Skeleton

Using multiple protectors for a policy

fscrypt supports the idea of protecting a single directory with multiple protectors. This means having access to any of the protectors is sufficient to decrypt the directory. This is useful for sharing data or setting up access control systems.

# Add an existing protector to the policy for some directory
>>>>> fscrypt status /mnt/disk
ext4 filesystem "/mnt/disk" has 3 protectors and 3 policies

PROTECTOR         LINKED   DESCRIPTION
7626382168311a9d  No       custom protector "Super Secret"
2c75f519b9c9959d  No       raw key protector "Skeleton"
6891f0a901f0065e  Yes (/)  login protector for joerichey

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:   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:16382f282d7b29ee27e6460151d03382
WARNING: All files using this policy will be accessible with this protector!!
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 16382f282d7b29ee27e6460151d03382.
>>>>> fscrypt status /mnt/disk/dir1
"/mnt/disk/dir1" is encrypted with fscrypt.

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

Protected with 2 protectors:
PROTECTOR         LINKED  DESCRIPTION
7626382168311a9d  No      custom protector "Super Secret"
2c75f519b9c9959d  No      raw key protector "Skeleton"

# Now the unlock command will prompt for which protector we want to use
>>>>> fscrypt unlock /mnt/disk/dir1
The available protectors are:
0 - custom protector "Super Secret"
1 - raw key protector "Skeleton"
Enter the number of protector to use: 1
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:16382f282d7b29ee27e6460151d03382
WARNING: All files using this policy will NO LONGER be accessible with this protector!!
Stop protecting policy 16382f282d7b29ee27e6460151d03382 with protector 2c75f519b9c9959d? [y/N] y
Protector 2c75f519b9c9959d no longer protecting policy 16382f282d7b29ee27e6460151d03382.

Quiet version

>>>>> 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

We would love to accept your contributions to fscrypt. See the CONTRIBUTING.md file for more information about signing the CLA and submitting a pull request.

Troubleshooting

In general, if you are encountering issues with fscrypt, open an issue, following the guidelines in CONTRIBUTING.md. We will try our best to help.

I changed my login passphrase, now all my directories are inaccessible

Usually, the PAM module pam_fscrypt.so will automatically detect changes to a user's login passphrase and update the user's fscrypt login protector so that they retain access their login-passphrase protected directories. However, sometimes a user's login passphrase can become desynchronized from their fscrypt login protector. This can happen if root assigns the user a new passphrase without providing the old one, if the user's login passphrase is managed by an external system such as LDAP, if the PAM module is not installed, or if the PAM module is not properly configured. See Enabling the PAM module for how to configure the PAM module.

To fix a user's login protector, find the corresponding protector ID by running fscrypt status "/". Then, change this protector's passphrase by running:

fscrypt metadata change-passphrase --protector=/:ID

Directories using my login passphrase are not automatically unlocking

First, directories won't unlock if your session starts without password authentication. The most common case of this is public-key ssh login. To trigger a password authentication event, run su $USER -c exit.

If your session did start with password authentication, then the following may be causing the issue:

  • The PAM module might not be configured correctly. Ensure you have correctly configured the PAM module.

  • If your login passphrase recently changed, then it might have gotten out of sync with your login protector. To fix this, manually change your login protector's passphrase to get it back in sync with your actual login passphrase.

  • Due to a bug in sshd, encrypted directories won't auto-unlock when logging in with ssh using the ChallengeResponseAuthentication ssh authentication method, which is also called KbdInteractiveAuthentication. This ssh authentication method implements password authentication by default, so it might appear similar to PasswordAuthentication. However, only PasswordAuthentication works with fscrypt. To avoid this issue, make sure that your /etc/ssh/sshd_config file contains PasswordAuthentication yes, UsePAM yes, and either ChallengeResponseAuthentication no or KbdInteractiveAuthentication no.

Getting "encryption not enabled" on an ext4 filesystem

This is usually caused by your ext4 filesystem not having the encrypt feature flag enabled. The encrypt feature flag allows the filesystem to contain encrypted files. (It doesn't actually encrypt anything by itself.)

Before enabling encrypt on your ext4 filesystem, first ensure that all of the following are true for you:

  • You only need to use your filesystem on kernels v4.1 and later.

    (Kernels v4.0 and earlier can't mount ext4 filesystems that have the encrypt feature flag.)

  • Either you only need to use your filesystem on kernels v5.5 and later, or your kernel page size (run getconf PAGE_SIZE) and filesystem block size (run tune2fs -l /dev/device | grep 'Block size') are the same.

    (Both values will almost always be 4096, but they may differ if your filesystem is very small, if your system uses the PowerPC CPU architecture, or if you overrode the default block size when you created the filesystem. Only kernels v5.5 and later support ext4 encryption in such cases.)

  • Either you aren't using GRUB to boot directly off the filesystem in question, or you are using GRUB 2.04 or later.

    (Old versions of GRUB can't boot from ext4 filesystems that have encrypt enabled. If, like most people, you have a separate /boot partition, you are fine. You are also fine if you are using the GRUB Debian package 2.02-2 or later [not 2.02_beta*], including the version in Ubuntu 18.04 and later, since the patch to support encrypt was backported.)

After verifying all of the above, enable encrypt by running:

tune2fs -O encrypt /dev/device

If you need to undo this, first delete all encrypted files and directories on the filesystem. Then, run:

fsck -fn /dev/device
debugfs -w -R "feature -encrypt" /dev/device
fsck -fn /dev/device

If you've enabled encrypt but you still get the "encryption not enabled" error, then the problem is that ext4 encryption isn't enabled in your kernel config. See Runtime dependencies for how to enable it.

Getting "user keyring not linked into session keyring"

Some older versions of Ubuntu didn't link the user keyring into the session keyring, which caused problems with fscrypt.

To avoid this issue, upgrade to Ubuntu 20.04 or later.

Getting "Operation not permitted" when moving files into an encrypted directory

Originally, filesystems didn't return the correct error code when attempting to rename unencrypted files (or files with a different encryption policy) into an encrypted directory. Specifically, they returned EPERM instead of EXDEV, which caused mv to fail rather than fall back to a copy as expected.

This bug was fixed in version 5.1 of the mainline Linux kernel, as well as in versions 4.4 and later of the LTS (Long Term Support) branches of the Linux kernel; specifically v4.19.155, 4.14.204, v4.9.242, and v4.4.242.

If the kernel can't be upgraded, this bug can be worked around by explicitly copying the files instead, e.g. with cp.

IMPORTANT: Encrypting existing files can be insecure. Before doing so, read Encrypting existing files.

Getting "Package not installed" when trying to use an encrypted directory

Trying to create or open an encrypted file will fail with ENOPKG ("Package not installed") when the kernel doesn't support one or more of the cryptographic algorithms used by the file or its directory. Note that fscrypt encrypt and fscrypt unlock will still succeed; it's only using the directory afterwards that will fail.

The kernel will always support the algorithms that fscrypt uses by default. However, if you changed the contents and/or filenames encryption algorithms in /etc/fscrypt.conf, then you may run into this issue. To fix it, enable the needed CONFIG_CRYPTO_* options in your Linux kernel configuration. See the kernel documentation for details about which option(s) are required for each encryption mode.

Some processes can't access unlocked encrypted files

This issue is caused by a limitation in the original design of Linux native filesystem encryption which made it difficult to ensure that all processes can access unlocked encrypted files. This issue can manifest in many ways, such as:

  • SSH to a user with an encrypted home directory not working, even when that directory is already unlocked

  • Docker containers being unable to access encrypted files that were unlocked from outside the container

  • NetworkManager being unable to access certificates stored in the user's already-unlocked encrypted home directory

  • Other system services being unable to access already-unlocked encrypted files

  • sudo sessions being unable to access already-unlocked encrypted files

  • A user being unable to access encrypted files that were unlocked by root

If an OS-level error is shown, it is ENOKEY ("Required key not available").

To fix this issue, first run fscrypt status $dir, where $dir is your encrypted directory. If the output contains policy_version:2, then your issue is something else, so stop reading now. If the output contains policy_version:1 or doesn't contain any mention of policy_version, then you'll need to upgrade your directory(s) to policy version 2. To do this:

  1. Upgrade to Linux kernel v5.4 or later.

  2. Upgrade to fscrypt v0.2.7 or later.

  3. Run sudo fscrypt setup --force.

  4. Re-encrypt your encrypted directory(s). Since files cannot be (re-)encrypted in-place, this requires replacing them with new directories. For example:

      fscrypt unlock dir  # if not already unlocked
      mkdir dir.new
      fscrypt encrypt dir.new
      cp -a -T dir dir.new
      find dir -type f -print0 | xargs -0 shred -n1 --remove=unlink
      rm -rf dir
      mv dir.new dir
    

    You don't need to create a new protector. I.e., when fscrypt encrypt asks for a protector, just choose the one you were using before.

  5. fscrypt status on your directory(s) should now show policy_version:2, and the issue should be gone.

Note that once your directories are using policy version 2, they will only be usable with Linux kernel v5.4 and later and fscrypt v0.2.6 and later. So be careful not to downgrade your software past those versions.

This issue can also be fixed by setting "use_fs_keyring_for_v1_policies": true in /etc/fscrypt.conf, as described in Configuration file. This avoids needing to upgrade directories to policy version 2. However, this has some limitations, and the same kernel and fscrypt prerequisites still apply for this option to take effect. It is recommended to upgrade your directories to policy version 2 instead.

Users can access other users' unlocked encrypted files

This is working as intended. When an encrypted directory is unlocked (or locked), it is unlocked (or locked) for all users. Encryption is not access control; the Linux kernel already has many access control mechanisms, such as the standard UNIX file permissions, that can be used to control access to files.

Setting the mode of your encrypted directory to 0700 will prevent users other than the directory's owner and root from accessing it while it is unlocked. In fscrypt v0.2.5 and later, fscrypt encrypt sets this mode automatically.

Having the locked/unlocked status of directories be global instead of per-user may seem unintuitive, but it is actually the only logical way. The encryption is done by the filesystem, so in reality the filesystem either has the key or it doesn't. And once it has the key, any additional checks of whether particular users "have" the key would be OS-level access control checks (not cryptography) that are redundant with existing OS-level access control mechanisms.

Similarly, any attempt of the filesystem encryption feature to prevent root from accessing unlocked encrypted files would be pointless. On Linux systems, root is usually all-powerful and can always get access to files in ways that cannot be prevented, e.g. setuid() and ptrace(). The only reliable way to limit what root can do is via a mandatory access control system, e.g. SELinux.

The original design of Linux native filesystem encryption actually did put the keys into per-user keyrings. However, this caused a massive number of problems, as it's actually very common that encrypted files need to be accessed by processes running under different user IDs -- even if it may not be immediately apparent.

Getting "Required key not available" when backing up locked encrypted files

Encrypted files can't be backed up while locked; you need to unlock them first. For details, see Backup, restore, and recovery.

The reported size of encrypted symlinks is wrong

Originally, filesystems didn't conform to POSIX when reporting the size of encrypted symlinks, as they gave the size of the ciphertext symlink target rather than the size of the plaintext target. This would make the reported size of symlinks appear to be slightly too large when queried using lstat() or similar system calls. Most programs don't care about this, but in rare cases programs can depend on the filesystem reporting symlink sizes correctly.

This bug was fixed in version 5.15 of the mainline Linux kernel, as well as in versions 4.19 and later of the LTS (Long Term Support) branches of the Linux kernel; specifically v5.10.63, v5.4.145, and v4.19.207.

If the kernel can't be upgraded, the only workaround for this bug is to update any affected programs to not depend on symlink sizes being reported correctly.

Legal

Copyright 2017 Google Inc. under the Apache 2.0 License; see the LICENSE file for more information.

Author: Joe Richey [email protected]

This is not an official Google product.

fscrypt's People

Contributors

anatol avatar audeoudh avatar bitcodr avatar dependabot[bot] avatar dimitry-ishenko avatar dvrkps avatar ebiggers avatar etrnls avatar flowdalic avatar fristonio avatar fstanis avatar gibeom-gwon avatar hobbitalastair avatar ilius avatar josephlr avatar kant avatar mhalcrow-google avatar ramcq avatar sanjaymsh avatar tklauser avatar vivekv96 avatar wjt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fscrypt's Issues

[bug] pam_fscrypt doesn't locks and clear keyring after logout

Thank you for fixing issues I reported. Unfortunately I have another one.

I created user1 and created encrypted directory under his homedir using pam_passphrase method.

I added following fscrypt pam session module to my pam config:
session optional pam_fscrypt.so drop_caches lock_policies debug

When user1 logs in encrypted directory is correctly unlocked but after logout it's still unlocked and avalaible in plaintext. user1 key is still available in root keyring.

Invoking fscrypt purge manually correctly removes user1 keys and lock encrypted directory.

fscrypt --version   
Version:
  0.2.1
pam_fscrypt[928]: OpenSession()
pam_fscrypt[928]: Session count for UID=995 updated to 1
pam_fscrypt[928]: Setreuid(995, 0) = <nil>
pam_fscrypt[928]: keyringID(_uid.995) = 382539738, <nil>
pam_fscrypt[928]: Setreuid(0, 995) = <nil>
pam_fscrypt[928]: KeyctlLink(382539738, -2) = <nil>
pam_fscrypt[928]: Setreuid(0, 0) = <nil>
pam_fscrypt[928]: keyringID(_uid.0) = 953047531, <nil>
pam_fscrypt[928]: KeyctlLink(953047531, -2) = <nil>
pam_fscrypt[928]: KeyctlLink(382539738, 953047531) = <nil>
pam_fscrypt[928]: Setting privileges to "sddm"
pam_fscrypt[928]: Setregid(-1, 995) = <nil>
pam_fscrypt[928]: Setgroups([995]) = <nil>
pam_fscrypt[928]: Setreuid(-1, 995) = <nil>
pam_fscrypt[928]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[928]: creating context for "sddm"
pam_fscrypt[928]: found ext4 filesystem "/" (/dev/sda1)
pam_fscrypt[928]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[928]: found 1 descriptor(s)
pam_fscrypt[928]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[928]: no protector to unlock: no PAM protector for UID=995 on "/"
pam_fscrypt[928]: Setting privileges to "root"
pam_fscrypt[928]: Setreuid(-1, 0) = <nil>
pam_fscrypt[928]: Setregid(-1, 0) = <nil>
pam_fscrypt[928]: Setgroups([0 1 2 3 4 6 10 19]) = <nil>
pam_fscrypt[928]: pam func succeeded
pam_fscrypt[1024]: OpenSession()
pam_fscrypt[1024]: Session count for UID=1001 updated to 1
pam_fscrypt[1024]: KeyctlLink(620474931, 953047531) = <nil>
pam_fscrypt[1024]: Setting privileges to "user1"
pam_fscrypt[1024]: Setregid(-1, 1001) = <nil>
pam_fscrypt[1024]: Setgroups([1001 6 7 90 91 92 93 95 96 98]) = <nil>
pam_fscrypt[1024]: Setreuid(-1, 1001) = <nil>
pam_fscrypt[1024]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[1024]: creating context for "user1"
pam_fscrypt[1024]: found ext4 filesystem "/" (/dev/sda1)
pam_fscrypt[1024]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[1024]: found 1 descriptor(s)
pam_fscrypt[1024]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1024]: Getting protector d61a252a36ed673d from option
pam_fscrypt[1024]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1024]: listing descriptors in "/.fscrypt/policies"
pam_fscrypt[1024]: found 0 descriptor(s)
pam_fscrypt[1024]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1024]: listing descriptors in "/home/.fscrypt/policies"
pam_fscrypt[1024]: found 1 descriptor(s)
pam_fscrypt[1024]: successfully read metadata from "/home/.fscrypt/policies/ad38f36028a00960"
pam_fscrypt[1024]: got data for ad38f36028a00960 from "/home"
pam_fscrypt[1024]: stat /run/user/995/.fscrypt: permission denied
pam_fscrypt[1024]: stat /run/user/995/.fscrypt/policies: permission denied
pam_fscrypt[1024]: stat /run/user/995/.fscrypt/protectors: permission denied
pam_fscrypt[1024]: stat /sys/firmware/efi/efivars/.fscrypt: invalid argument
pam_fscrypt[1024]: stat /sys/firmware/efi/efivars/.fscrypt/policies: invalid argument
pam_fscrypt[1024]: stat /sys/firmware/efi/efivars/.fscrypt/protectors: invalid argument
pam_fscrypt[1024]: stat /sys/kernel/debug/.fscrypt: permission denied
pam_fscrypt[1024]: stat /sys/kernel/debug/.fscrypt/policies: permission denied
pam_fscrypt[1024]: stat /sys/kernel/debug/.fscrypt/protectors: permission denied
pam_fscrypt[1024]: unlocking 1 policies protected with AUTHTOK
pam_fscrypt[1024]: running passphrase hash for protector d61a252a36ed673d
pam_fscrypt[1024]: valid wrapping key for protector d61a252a36ed673d
pam_fscrypt[1024]: keyringID(session) = 285177417, <nil>
pam_fscrypt[1024]: KeyctlSearch(285177417, keyring, _uid.1001) = 620474931, <nil>
pam_fscrypt[1024]: KeyctlSearch(620474931, logon, ext4:ad38f36028a00960) = -1, required key not available
pam_fscrypt[1024]: keyringID(session) = 285177417, <nil>
pam_fscrypt[1024]: KeyctlSearch(285177417, keyring, _uid.1001) = 620474931, <nil>
pam_fscrypt[1024]: KeyctlAddKey(logon, ext4:ad38f36028a00960, <data>, 620474931) = 647228005, <nil>
pam_fscrypt[1024]: policy ad38f36028a00960 provisioned
pam_fscrypt[1024]: Setting privileges to "root"
pam_fscrypt[1024]: Setreuid(-1, 0) = <nil>
pam_fscrypt[1024]: Setregid(-1, 0) = <nil>
pam_fscrypt[1024]: Setgroups([0 1 2 3 4 6 10 19]) = <nil>
pam_fscrypt[1024]: pam func succeeded
pam_fscrypt[1135]: OpenSession()
pam_fscrypt[1135]: Session count for UID=1001 updated to 2
pam_fscrypt[1135]: Setreuid(1001, 0) = <nil>
pam_fscrypt[1135]: keyringID(_uid.1001) = 620474931, <nil>
pam_fscrypt[1135]: Setreuid(0, 1001) = <nil>
pam_fscrypt[1135]: KeyctlLink(620474931, -2) = <nil>
pam_fscrypt[1135]: Setreuid(0, 0) = <nil>
pam_fscrypt[1135]: keyringID(_uid.0) = 953047531, <nil>
pam_fscrypt[1135]: KeyctlLink(953047531, -2) = <nil>
pam_fscrypt[1135]: KeyctlLink(620474931, 953047531) = <nil>
pam_fscrypt[1135]: Setting privileges to "user1"
pam_fscrypt[1135]: Setregid(-1, 1001) = <nil>
pam_fscrypt[1135]: Setgroups([1001 6 7 90 91 92 93 95 96 98]) = <nil>
pam_fscrypt[1135]: Setreuid(-1, 1001) = <nil>
pam_fscrypt[1135]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[1135]: creating context for "user1"
pam_fscrypt[1135]: found ext4 filesystem "/" (/dev/sda1)
pam_fscrypt[1135]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[1135]: found 1 descriptor(s)
pam_fscrypt[1135]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1135]: Getting protector d61a252a36ed673d from option
pam_fscrypt[1135]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1135]: listing descriptors in "/.fscrypt/policies"
pam_fscrypt[1135]: found 0 descriptor(s)
pam_fscrypt[1135]: successfully read metadata from "/.fscrypt/protectors/d61a252a36ed673d"
pam_fscrypt[1135]: listing descriptors in "/home/.fscrypt/policies"
pam_fscrypt[1135]: found 1 descriptor(s)
pam_fscrypt[1135]: successfully read metadata from "/home/.fscrypt/policies/ad38f36028a00960"
pam_fscrypt[1135]: got data for ad38f36028a00960 from "/home"
pam_fscrypt[1135]: stat /run/user/995/.fscrypt: permission denied
pam_fscrypt[1135]: stat /run/user/995/.fscrypt/policies: permission denied
pam_fscrypt[1135]: stat /run/user/995/.fscrypt/protectors: permission denied
pam_fscrypt[1135]: stat /sys/firmware/efi/efivars/.fscrypt: invalid argument
pam_fscrypt[1135]: stat /sys/firmware/efi/efivars/.fscrypt/policies: invalid argument
pam_fscrypt[1135]: stat /sys/firmware/efi/efivars/.fscrypt/protectors: invalid argument
pam_fscrypt[1135]: stat /sys/kernel/debug/.fscrypt: permission denied
pam_fscrypt[1135]: stat /sys/kernel/debug/.fscrypt/policies: permission denied
pam_fscrypt[1135]: stat /sys/kernel/debug/.fscrypt/protectors: permission denied
pam_fscrypt[1135]: unlocking 1 policies protected with AUTHTOK
pam_fscrypt[1135]: Setting privileges to "root"
pam_fscrypt[1135]: Setreuid(-1, 0) = <nil>
pam_fscrypt[1135]: Setregid(-1, 0) = <nil>
pam_fscrypt[1135]: Setgroups([0 1 2 3 4 6 10 19]) = <nil>
pam_fscrypt[1135]: pam func failed: unlocking protector d61a252a36ed673d: AUTHTOK data missing: No module specific data is present
pam_fscrypt[1024]: CloseSession(map[debug:true drop_caches:true lock_policies:true])
pam_fscrypt[1024]: Session count for UID=1001 updated to 1
pam_fscrypt[1024]: count is 1 and we are not locking
pam_fscrypt[1024]: pam func succeeded
pam_fscrypt[936]: CloseSession(map[drop_caches:true lock_policies:true debug:true])
pam_fscrypt[936]: count is 0 and we are not locking
pam_fscrypt[936]: pam func failed: open /run/fscrypt/995.count: permission denied

Policies are never provisioned

Note that in encryptPath() the policy should be deprovisioned on failure to set the appropriate policy. However, the actual deprovisioning is here. Note that this deprovisioning is unconditional, so fscrypt encrypt DIRECTORY will never result in an unlocked directory.

Document exact specifics of udev dependancy

With #54, the directory /dev/disk/by-uuid and its contents are now necessary to establish cross filesystem links. This means use of these links now depends on a specific default udev rule, namely 60-persistent-storage.rules. The source can be found in the systemd tree, eudev tree, and the old udev tree.

The documentation (probably part of #10) should explain this an other dependencies in a single section. It should also explain when these dependencies are necessary (build-time, run-time, link creation time, etc..).

Protectors can be improperly reverted

In cmd/fscrypt/commands.go, Protectors should be reverted if they are created. The reversion on failure is here. But this has a problem.

If the protector is selected (not created) in selectOrCreateProtector() the protector will be reverted regardless on any error. This means a failure after selection can result in data loss. The documentation for selectOrCreateProtector() is also wrong, leading to this confusion.

[bug] Logged users can view each other encrypted files in plaintext

I noticed that logged user can view files from other logged users encrypted directories even as they see encrypted directory status as locked and don't have relevant key in their keyring. Is it side effect of linking user keyring to root's? I tested this on Archlinux with fscrypt --version 0.2.1-1-ga949b13 while logging in with VT console. Also all users in Arch share the same GID "users" by default. After user logout directory is properly visible as encrypted.

Encrypted directory status viewed as user2:

$ fscrypt status /home/user1
"/home/user1" is encrypted with fscrypt.

Policy:   949471831dcf55cf
Unlocked: No

Protected with 1 protector:
PROTECTOR         LINKED  DESCRIPTION
6682ae84e70e99b3  No      login protector for user1

User2 keyring:

$ keyctl show
Session Keyring
 168271410 --alswrv   1002  1002  keyring: _ses
 840784887 --alswrv   1002 65534   \_ keyring: _uid.1002
 800661253 --alsw-v   1002  1002       \_ logon: ext4:13cb92d62226353b

Encrypted directory view as user2:

$ ls -al /home/user1/
total 12
drwxr-xr-x 2 user1 user1 4096 Sep  3 16:14 .
drwxr-xr-x 6 root  root  4096 Sep  3 16:10 ..
-rw-r--r-- 1 user1 user1  225 Sep  8 12:02 .bash_history

Encrypted file view as user2:

$ cat /home/user1/.bash_history
ls -al
fscrypt encrypt /home/user1
exit
exit
fscrypt status /home/user1/
exit
exit
exit
exit
chmod 644 .bash_history 
logout
exit
exit
exit

Build failure on 32 bit architectures

The PointerSlice() function, added by 0b643ea, is causing build failures on 32 bit architectures (verified on armhf and i386 in Ubuntu Artful). Here's the relevant snippet from the build log:

src/github.com/google/fscrypt/util/util.go:49: type [1073741824]unsafe.Pointer larger than address space
src/github.com/google/fscrypt/util/util.go:49: type [1073741824]unsafe.Pointer too large

Here's the code around line 49:

    46	// PointerSlice takes a pointer to an array of pointers and views it as a slice
    47	// of pointers. Note, indexing into this slice is unsafe.
    48	func PointerSlice(ptr unsafe.Pointer) []unsafe.Pointer {
    49		return (*[1 << 30]unsafe.Pointer)(ptr)[:]
    50	}

I'm not sure how stable these links will be longterm but here are links to the full build logs:

pam_fscrypt messes up user groups during login

I've added pam_fscrypt to /etc/pam.d/system-auth (on Arch Linux) as described in the README:

auth      required  pam_unix.so     try_first_pass nullok
auth      optional  pam_permit.so
auth      required  pam_env.so
auth      optional  pam_fscrypt.so

account   required  pam_unix.so
account   optional  pam_permit.so
account   required  pam_time.so

password  required  pam_unix.so     try_first_pass nullok sha512 shadow
password  optional  pam_permit.so
password  optional  pam_fscrypt.so

session   required  pam_limits.so
session   required  pam_unix.so
session   optional  pam_permit.so
session   optional  pam_fscrypt.so  drop_caches lock_policies

With pam_fscrypt enabled, I'm no longer in the wheel group after login for some reason, which means I can no longer use sudo. Instead, it adds me to the root group:

$ id
uid=1000(i3test) gid=1000(i3test) groups=1000(i3test),0(root)

With session optional pam_fscrypt.so commented out:

$ id
uid=1000(i3test) gid=1000(i3test) groups=1000(i3test),985(wheel)

Log:

login[434]: pam_unix(login:session): session opened for user i3test by LOGIN(uid=0)
pam_fscrypt[434]: OpenSession()
pam_fscrypt[434]: Session count for UID=1000 updated to 1
pam_fscrypt[434]: KeyctlLink(483117192, 57274768) = <nil>
pam_fscrypt[434]: Setting privileges to "i3test"
pam_fscrypt[434]: Setregid(-1, 1000) = <nil>
pam_fscrypt[434]: Setgroups([1000 985]) = <nil>
pam_fscrypt[434]: Setreuid(-1, 1000) = <nil>
pam_fscrypt[434]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[434]: creating context for "i3test"
pam_fscrypt[434]: found ext4 filesystem "/" (/dev/sda2)
pam_fscrypt[434]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[434]: found 0 descriptor(s)
pam_fscrypt[434]: no protector to unlock: no PAM protector for UID=1000 on "/"
pam_fscrypt[434]: Setting privileges to "root"
pam_fscrypt[434]: Setreuid(-1, 0) = <nil>
pam_fscrypt[434]: Setregid(-1, 0) = <nil>
pam_fscrypt[434]: Setgroups([0]) = <nil>
pam_fscrypt[434]: pam func succeeded
login[434]: LOGIN ON tty1 BY i3test
login[434]: pam_unix(login:session): session closed for user i3test
pam_fscrypt[434]: CloseSession(map[drop_caches:true lock_policies:true debug:true])
pam_fscrypt[434]: Session count for UID=1000 updated to 0
pam_fscrypt[434]: locking polices protected with login protector
pam_fscrypt[434]: KeyctlLink(483117192, 57274768) = <nil>
pam_fscrypt[434]: Setting privileges to "i3test"
pam_fscrypt[434]: Setregid(-1, 1000) = <nil>
pam_fscrypt[434]: Setgroups([1000 985]) = <nil>
pam_fscrypt[434]: Setreuid(-1, 1000) = <nil>
pam_fscrypt[434]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[434]: creating context for "i3test"
pam_fscrypt[434]: found ext4 filesystem "/" (/dev/sda2)
pam_fscrypt[434]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[434]: found 0 descriptor(s)
pam_fscrypt[434]: nothing to lock: no PAM protector for UID=1000 on "/"
pam_fscrypt[434]: Setting privileges to "root"
pam_fscrypt[434]: Setreuid(-1, 0) = <nil>
pam_fscrypt[434]: Setregid(-1, 0) = <nil>
pam_fscrypt[434]: Setgroups([0]) = <nil>
pam_fscrypt[434]: dropping appropriate filesystem caches at session close
pam_fscrypt[434]: syncing changes to filesystem
pam_fscrypt[434]: freeing reclaimable inodes and dentries
pam_fscrypt[434]: pam func succeeded
kernel: login (434): drop_caches: 2

Any ideas? :)

Document memory failures

fscrypt locks keys in memory for security. However, if the user's limit on the total amount of memory (see yours by running ulimit -l) is exceeded, creating a new key fails with EAGAIN. This is because the mmap syscall returns EAGAIN when the memory limit is reached (see docs).

The returned error message of "resource temporarily unavailable" is not very helpful. A better message should be returned and an explanation printed.

Add fscrypt man page

The fscrypt tool should have a man page so that users can easily and locally find more information on how to use fscrypt. The man page should probably live in section 8 since fscrypt is mostly a system administration tool.

Use user keyring instead of session keyring

Currently fscrypt adds keys to session keyring (KEY_SPEC_SESSION_KEYRING). Applications started within systemd --user instance have their own session keyring which means they would have no access to encrypted directories. To fix this we need add keys to user keyring (KEY_SPEC_USER_KEYRING) instead.

You can test it by invoking systemd-run --user keyctl show,and check logs, the keyring is empty.

Using user keyring is recommended by systemd developers, see systemd/systemd#1299 (comment)

neithernut/pam_e4crypt#14
systemd/systemd#5715

Add PAM module

As mentioned in the README, the idea of protecting directories with a login passphrase is incomplete without a PAM module. This PAM module will need to support the following functionality:

  • Automatically re-wrapping a user's login protector when their PAM passphrase changes.
  • Automatically unlocking directories on login

The road map for changes to incorporate the PAM module is as follows:

  • (#21) Refactoring the pam package to support the additional functionality.
  • (#3, #18) Improvements to the actions package making unlocking Policies easier. See #3 and #18
  • (#25) Writing the PAM module itself. This will be a package exporting the correct identifiers built as a .so.
  • (#25) Adding build support in the Makefile
  • (#25) Updating the Documentation

File names available in plaintext after logout using SDDM

When using SDDM display manager, filenames are still available in plaintext after user logs out. It's weird as file contents remain encrypted. It doesn't happen if user logs in from console. It also happened before #57 was fixed and I executed fscrypt purge command on exit from script.

fscrypt --version
Version:
  0.2.1-9-gd6efd2a

Encrypted directory status before login:

# fscrypt status /home/user1/
"/home/user1" is encrypted with fscrypt.

Policy:   949471831dcf55cf
Unlocked: No

Protected with 1 protector:
PROTECTOR         LINKED   DESCRIPTION
6682ae84e70e99b3  Yes (/)  login protector for user1

Encrypted directory view before login:

# ls -al /home/user1
total 44
drwxr-xr-x  8 user1 user1 4096 Oct  1 21:55 .
drwxr-xr-x  6 root  root  4096 Sep  3 16:10 ..
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 4KuOWyB8JVvtSjQ5wWBs+3UWsPIAtebNN03,X6EhRRD
-rw-------  1 user1 user1   51 Oct  1 21:55 7Gkj14k6MhIjhqp,YpbkzY0ZmW5CZ8NWfjtIUvuXVYN
drwxr-xr-x  4 user1 user1 4096 Oct  1 21:56 cYjQyFUTZ0aueNUy49A2gC6rqu+hr9YqG+J0YxZuogN
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 dUJK0ZvNyVKTTyY2aT4uwV70oxGuP4UpaaNTHH6f,PI
-rw-------  1 user1 user1   16 Oct  1 21:55 gaVOjkDXQ,epFAzE0U9oaiJ1RZegg,E46fybSNZxyZJ
drwxr-xr-x 12 user1 user1 4096 Oct  1 21:56 GhiHtwJJ6Udq2iruRTdskoM3gOuZO0qwD8Y7db9ViYK
-rw-r--r--  1 user1 user1  336 Oct  1 21:55 mA2atU6muhkdiJ8+x11CDrSijNnTx6GymhU5fZQSIRM
drwx------  2 user1 user1 4096 Oct  1 21:55 t3rX5lOToba9YDfnn,05o5AOxqs,8C+lilp7ayKpy5M
drwx------  2 user1 user1 4096 Oct  1 21:55 xavy48JtAUzUGMEFTKfrwd,ckOdtF0I09FkVArPrg1N

user1 logs in:

# journalctl -f |grep fscrypt
pam_fscrypt[1162]: Authenticate()
pam_fscrypt[1162]: Setreuid(1001, 0) = <nil>
pam_fscrypt[1162]: keyringID(_uid.1001) = 848488077, <nil>
pam_fscrypt[1162]: Setreuid(0, 1001) = <nil>
pam_fscrypt[1162]: KeyctlLink(848488077, -2) = <nil>
pam_fscrypt[1162]: Setreuid(0, 0) = <nil>
pam_fscrypt[1162]: keyringID(_uid.0) = 698375302, <nil>
pam_fscrypt[1162]: KeyctlLink(698375302, -2) = <nil>
pam_fscrypt[1162]: KeyctlLink(848488077, 698375302) = <nil>
pam_fscrypt[1162]: Setting privileges to "user1"
pam_fscrypt[1162]: Setregid(-1, 1001) = <nil>
pam_fscrypt[1162]: Setgroups([1001 6 7 90 91 92 93 95 96 98]) = <nil>
pam_fscrypt[1162]: Setreuid(-1, 1001) = <nil>
pam_fscrypt[1162]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[1162]: creating context for "user1"
pam_fscrypt[1162]: found ext4 filesystem "/" (/dev/sda)
pam_fscrypt[1162]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[1162]: found 1 descriptor(s)
pam_fscrypt[1162]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1162]: Getting protector 6682ae84e70e99b3 from option
pam_fscrypt[1162]: copying AUTHTOK for use in the session open
pam_fscrypt[1162]: Setting privileges to "root"
pam_fscrypt[1162]: Setreuid(-1, 0) = <nil>
pam_fscrypt[1162]: Setregid(-1, 0) = <nil>
pam_fscrypt[1162]: Setgroups([0 1 2 3 4 6 10 19]) = <nil>
pam_fscrypt[1162]: pam func succeeded
pam_fscrypt[1162]: OpenSession()
pam_fscrypt[1162]: Session count for UID=1001 updated to 1
pam_fscrypt[1162]: KeyctlLink(848488077, 698375302) = <nil>
pam_fscrypt[1162]: Setting privileges to "user1"
pam_fscrypt[1162]: Setregid(-1, 1001) = <nil>
pam_fscrypt[1162]: Setgroups([1001 6 7 90 91 92 93 95 96 98]) = <nil>
pam_fscrypt[1162]: Setreuid(-1, 1001) = <nil>
pam_fscrypt[1162]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[1162]: creating context for "user1"
pam_fscrypt[1162]: found ext4 filesystem "/" (/dev/sda)
pam_fscrypt[1162]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[1162]: found 1 descriptor(s)
pam_fscrypt[1162]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1162]: Getting protector 6682ae84e70e99b3 from option
pam_fscrypt[1162]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1162]: listing descriptors in "/.fscrypt/policies"
pam_fscrypt[1162]: found 1 descriptor(s)
pam_fscrypt[1162]: successfully read metadata from "/.fscrypt/policies/949471831dcf55cf"
pam_fscrypt[1162]: got data for 949471831dcf55cf from "/"
pam_fscrypt[1162]: successfully read metadata from "/.fscrypt/policies/1

Encrypted directory view after user1 login:

# ls -al /home/user1
total 44
drwxr-xr-x  8 user1 user1 4096 Oct  1 21:59 .
drwxr-xr-x  6 root  root  4096 Sep  3 16:10 ..
drwxr-xr-x  4 user1 user1 4096 Oct  1 21:56 .cache
drwxr-xr-x 12 user1 user1 4096 Oct  1 21:59 .config
drwx------  2 user1 user1 4096 Oct  1 21:55 Desktop
-rw-------  1 user1 user1   16 Oct  1 21:55 .esd_auth
-rw-r--r--  1 user1 user1  336 Oct  1 21:55 .gtkrc-2.0
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 .kde4
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 .local
drwx------  2 user1 user1 4096 Oct  1 21:55 Temp
-rw-------  1 user1 user1   51 Oct  1 21:59 .Xauthority

user1 logout:

# journalctl -f |grep fscrypt
pam_fscrypt[1116]: CloseSession(map[debug:true lock_policies:true drop_caches:true])
pam_fscrypt[1116]: Session count for UID=1001 updated to 0
pam_fscrypt[1116]: locking polices protected with login protector
pam_fscrypt[1116]: KeyctlLink(7728276, 117932856) = <nil>
pam_fscrypt[1116]: Setting privileges to "user1"
pam_fscrypt[1116]: Setregid(-1, 1001) = <nil>
pam_fscrypt[1116]: Setgroups([1001 6 7 90 91 92 93 95 96 98]) = <nil>
pam_fscrypt[1116]: Setreuid(-1, 1001) = <nil>
pam_fscrypt[1116]: Reading config from "/etc/fscrypt.conf"
pam_fscrypt[1116]: creating context for "user1"
pam_fscrypt[1116]: found ext4 filesystem "/" (/dev/sda)
pam_fscrypt[1116]: listing descriptors in "/.fscrypt/protectors"
pam_fscrypt[1116]: found 1 descriptor(s)
pam_fscrypt[1116]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1116]: Getting protector 6682ae84e70e99b3 from option
pam_fscrypt[1116]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1116]: listing descriptors in "/.fscrypt/policies"
pam_fscrypt[1116]: found 1 descriptor(s)
pam_fscrypt[1116]: successfully read metadata from "/.fscrypt/policies/949471831dcf55cf"
pam_fscrypt[1116]: got data for 949471831dcf55cf from "/"
pam_fscrypt[1116]: successfully read metadata from "/.fscrypt/protectors/6682ae84e70e99b3"
pam_fscrypt[1116]: listing descriptors in "/home/.fscrypt/policies"
pam_fscrypt[1116]: found 1 descriptor(s)
pam_fscrypt[1116]: successfully read metadata from "/home/.fscrypt/policies/949471831dcf55cf"
pam_fscrypt[1116]: got data for 949471831dcf55cf from "/home"
pam_fscrypt[1116]: stat /sys/firmware/efi/efivars/.fscrypt: invalid argument
pam_fscrypt[1116]: stat /sys/firmware/efi/efivars/.fscrypt/policies: invalid argument
pam_fscrypt[1116]: stat /sys/firmware/efi/efivars/.fscrypt/protectors: invalid argument
pam_fscrypt[1116]: stat /sys/kernel/debug/.fscrypt: permission denied
pam_fscrypt[1116]: stat /sys/kernel/debug/.fscrypt/policies: permission denied
pam_fscrypt[1116]: stat /sys/kernel/debug/.fscrypt/protectors: permission denied

Encrypted directory status after user1 logout:

# fscrypt status /home/user1/
"/home/user1" is encrypted with fscrypt.

Policy:   949471831dcf55cf
Unlocked: No

Protected with 1 protector:
PROTECTOR         LINKED   DESCRIPTION
6682ae84e70e99b3  Yes (/)  login protector for user1

Encrypted directory view after user1 logout:

# ls -al /home/user1
total 44
drwxr-xr-x  8 user1 user1 4096 Oct  1 22:04 .
drwxr-xr-x  6 root  root  4096 Sep  3 16:10 ..
drwxr-xr-x  5 user1 user1 4096 Oct  1 22:05 .cache
drwxr-xr-x 12 user1 user1 4096 Oct  1 22:05 .config
drwx------  2 user1 user1 4096 Oct  1 21:55 Desktop
-rw-------  1 user1 user1   16 Oct  1 21:55 .esd_auth
-rw-r--r--  1 user1 user1  336 Oct  1 21:55 .gtkrc-2.0
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 .kde4
drwxr-xr-x  3 user1 user1 4096 Oct  1 21:55 .local
drwx------  2 user1 user1 4096 Oct  1 21:55 Temp
-rw-------  1 user1 user1   51 Oct  1 22:04 .Xauthority

Improve tests that depend on the filesystem

Many of the tests for fscrypt have a dependency on the environment. The either require

  • That TEST_FILESYSTEM_ROOT be set to the root an ext4 filesystem for testing.
  • That pam_fscrypt.so be installed.

To fix all this, we will add a command to setup the environment for integration tests, and skip the integration tests if the environment is not setup.

Automatically clear cache when fscrypt purge is used

As described in https://github.com/google/fscrypt#i-can-still-see-files-or-filenames-after-running-fscrypt-purge-mountpoint encryption keys are still available in kernel cache after issuing fscrypt purge command.

There is however option to clear kernel cache by changing /proc/sys/vm/drop_caches value to 2 or 3. That means fscrypt purge could send something like sync && echo 3 > /proc/sys/vm/drop_caches and the cache will be cleared. The downside is that fscrypt purge would need execution with sudo.

Add in mutation testing for fscrypt

We should have a better idea of how well our code is tested.

  • (#27) Have a way to automatically compute code coverage
  • (#27) Add a badge showing the code coverage
  • (#27) Track the coverage changes on PRs
  • Use mutation testing as well

encrypt subcommand incorrectly reports that the directory is ready for use

The fscrypt encrypt subcommand reports that, <DIR> is now encrypted, unlocked, and ready for use. but it doesn't actually unlock the directory:

$ mkdir -p encrypted && fscrypt encrypt encrypted/
Should we create a new protector? [y/N] y
Your data can be protected with one of the following sources:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 
Enter a name for the new protector: p1
Enter custom passphrase for protector "p1": 
Confirm passphrase: 
"encrypted/" is now encrypted, unlocked, and ready for use.
$ echo this is only a test > encrypted/test
-bash: encrypted/test: Required key not available
$ fscrypt status encrypted
"encrypted" is encrypted with fscrypt.

Policy:   9ac3aa2fa6413dd1
Unlocked: No

Protected with 1 protector:
PROTECTOR         LINKED  DESCRIPTION
69845814cae88b44  No      custom protector "p1"

Now I can unlock the directory and begin using it:

$ fscrypt unlock encrypted
Enter custom passphrase for protector "p1": 
"encrypted" is now unlocked and ready for use.
$ echo this is only a test > encrypted/test
$ cat encrypted/test
this is only a test

Set a more reasonable ramLimit

Fscrypt generates a reasonable set of defaults password hashing costs when creating /etc/fscrypt.conf. However, the ramLimit function is simply half the available system ram.

This poses a problem when using fscrypt on removable media. A password protector setup on a computer with a large amount of memory would be difficult to use on a computer with a small amount of memory. There is no real reason to consume multiple GiBs of RAM, the used memory just needs to not fit in any CPU caches.

Cryptsetup V2 uses a memory cost of 128MiB, which would be OK for any reasonable Linux system (Debian has a minimum memory of 128MiB on amd64).

This change would be completely backwards compatible, only changing the generated values for new /etc/fscrypt.conf files.

Error when unlocking filesystem.

Reported here, reproduced below:

I tested fscrypt with ext4, but I got this error:

root@pc1:/home/hamiltonp/Temp# fscrypt unlock mount/blah/
Enter custom passphrase for protector "test":
fscrypt unlock: permission denied: system error: could not insert key into the keyring

It persisted with password and keyfile method.

[question] Should bind-mounts be treated as separate filesystems?

I noticed that currently fscrypt treats directories mounted on existing filesystem with --bind option as separate mountpoints.
That means it needs executing fscrypt setup MOUNTPOINT on every directory mounted this way to make encryption available. Moreover it can create confusion when encrypted directory was created before bind-mounts were used:
fscrypt setup /
fscrypt encrypt /home/xxx (creates policy under /.fscrypt)
bind-mount /home to /home
fscrypt setup /home
fscrypt status /home/xxx (searches policy under /home/.fscrypt)

In that case user have to manually copy fscrypt metadata from /.fscrypt to /home/.fscrypt

Build instructions don't work

When following the build instructions in the readme, I got stuck at:
go get -d github.com/google/fscrypt
It comes back with:
can't load package: package github.com/google/fscrypt: no buildable Go source files in /home/pp/go/src/github.com/google/fscrypt
($GOROOT is /home/pp/go/root and $GOPATH is /home/pp/go here.)

/home/pp/go/src/github.com/google/fscrypt does contain the cloned contents of this repo.

Move to a better memory locking library

Fscrypt uses the Key struct to keep sensitive cryptographic data locked in memory and zeroed after use. However, this would be better spun out into a separate library (as it doesn't really deal much with fscrypt).

Luckily, @awnumar has written memguard a library for handling secrets in go. It does everything we want and more, but at the cost of requiring some changes to fscrypt (memguard.CatchInterrupt and memguard.SafeExit).

I'll need to do a more through read though of the code, but it looks good so far. In fact, the development of memguard incorporated things we learned with fscrypt. It really looks like this would be a strict improvement.

make: arch: Command not found

During build I am now seeing the following error:

make: arch: Command not found
go build --ldflags '-s -w -X "main.version=v0.2.3-2-gbd2ca31" -X "main.buildTime=Wed Feb 14 13:21:43 -03 2018" -extldflags "-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"' -o bin/fscrypt ./cmd/fscrypt
go build -buildmode=c-shared --ldflags '-s -w -X "main.version=v0.2.3-2-gbd2ca31" -X "main.buildTime=Wed Feb 14 13:21:43 -03 2018" -extldflags "-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now"' -o bin/pam_fscrypt.so ./pam_fscrypt
rm -f bin/pam_fscrypt.h

The build succeeds nonetheless. Is this expected? It might be related to commit 3326520

Insulate PAM module against panicking

As seen in #42, bugs in pam_fscrypt will crash the login process, making it very difficult to restore a buggy system. This is not desirable. We should catch all panics, log the stack trace, and return an error for the module.

Crashing the process calling into PAM is never desirable.

[question] user keyring still linked to root keyring after fscrypt purge command

I noticed that fscrypt purge correctly clear user keyring but it keeps it linked to root keyring

Before user unlocks encrypted directory:

# keyctl show
Session Keyring
 500577725 --alswrv      0     0  keyring: _ses
 749555953 --alswrv      0 65534   \_ keyring: _uid.0

After user unlocks encrypted directory:

# keyctl show
Session Keyring
 500577725 --alswrv      0     0  keyring: _ses
 749555953 --alswrv      0 65534   \_ keyring: _uid.0
 173465956 ---lswrv   1001 65534       \_ keyring: _uid.1001
 462364131 --alsw-v   1001  1001           \_ logon: ext4:949471831dcf55cf

After fscrypt purge / --force --user=user1

# keyctl show
Session Keyring
 500577725 --alswrv      0     0  keyring: _ses
 749555953 --alswrv      0 65534   \_ keyring: _uid.0
 173465956 ---lswrv   1001 65534       \_ keyring: _uid.1001

Is it correct behavior? I think it should be back to clean state which means unlinking user keyring from root keyring.

[documentation] ext4 encryption and grub

https://github.com/google/fscrypt#getting-encryption-not-enabled-on-an-ext4-filesystem

Note: It is actually possible to get GRUB to boot an encrypted ext4 filesystem. However, it requires GRUB 2.02 (NOT the 2.02 beta) to be installed as the bootloader. As this version was released in April 2017, most systems WILL FAIL TO BOOT with an ext4 encrypted boot directory

This information is not 100% accurate. grub 2.02 was tagged 2017-04-25: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=e54c99aaff5e5f6f5d3b06028506c57e66d8ef77

Ext4 encryption patch landed 2017-06-29: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=734668238fcc0ef691a080839e04f33854fa133a so it's not part of 2.02 upstream release.

Debian cherry-picked this patch to their 2.02 package https://anonscm.debian.org/cgit/pkg-grub/grub.git/commit/?id=29c8a3e93ad5c37599ac3281e59a7452c7c23928 but not every distro did.

Just found this hard way with grub rescue shell ๐Ÿ˜„

Hitting Ctrl-C during sudo prompt causes a segmentation fault

Test case:

  1. sudo echo lol
  2. Hit Ctrl-C to cancel password input.

Result:

[sudo] password for seba: 
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7fa539940f11]

runtime stack:
runtime.throw(0x7fa53576536c, 0x2a)
	/usr/lib/go/src/runtime/panic.go:605 +0x97
runtime.sigpanic()
	/usr/lib/go/src/runtime/signal_unix.go:351 +0x2bc

goroutine 17 [syscall, locked to thread]:
runtime.cgocall(0x7fa53575b580, 0xc4200c1cb8, 0x29)
	/usr/lib/go/src/runtime/cgocall.go:132 +0xea fp=0xc4200c1c88 sp=0xc4200c1c48 pc=0x7fa5355f374a
github.com/google/fscrypt/pam._Cfunc_copyIntoSecret(0x0, 0x0)
	github.com/google/fscrypt/pam/_obj/_cgo_gotypes.go:106 +0x4c fp=0xc4200c1cb8 sp=0xc4200c1c88 pc=0x7fa53571b70c
github.com/google/fscrypt/pam.(*Handle).SetSecret.func1(0x0, 0x7fa53571c7a1)
	/home/seba/.cache/pacaur/fscrypt-git/src/go/src/github.com/google/fscrypt/pam/pam.go:98 +0x62 fp=0xc4200c1cf0 sp=0xc4200c1cb8 pc=0x7fa53571cfc2
github.com/google/fscrypt/pam.(*Handle).SetSecret(0xc42000c9e0, 0x7fa53575dfc3, 0xf, 0x0, 0x0, 0x0)
	/home/seba/.cache/pacaur/fscrypt-git/src/go/src/github.com/google/fscrypt/pam/pam.go:98 +0x2d fp=0xc4200c1d38 sp=0xc4200c1cf0 pc=0x7fa53571c65d
main.Authenticate(0xc42000c9e0, 0xc4200108a0, 0x0, 0x0)
	/home/seba/.cache/pacaur/fscrypt-git/src/go/src/github.com/google/fscrypt/pam_fscrypt/pam_fscrypt.go:75 +0x256 fp=0xc4200c1da8 sp=0xc4200c1d38 pc=0x7fa5357576c6
main.RunPamFunc(0x7fa535a01df8, 0x55af85c4b080, 0x0, 0x0, 0x0)
	/home/seba/.cache/pacaur/fscrypt-git/src/go/src/github.com/google/fscrypt/pam_fscrypt/run_fscrypt.go:82 +0x20c fp=0xc4200c1e40 sp=0xc4200c1da8 pc=0x7fa53575915c
main.pam_sm_authenticate(0x55af85c4b080, 0x8000, 0x0, 0xc400000008)
	/home/seba/.cache/pacaur/fscrypt-git/src/go/src/github.com/google/fscrypt/pam_fscrypt/pam_fscrypt.go:262 +0x4b fp=0xc4200c1e78 sp=0xc4200c1e40 pc=0x7fa535758dab
main._cgoexpwrap_058fc3b736e8_pam_sm_authenticate(0x55af85c4b080, 0x8000, 0x0, 0x0)
	github.com/google/fscrypt/pam_fscrypt/_obj/_cgo_gotypes.go:62 +0x47 fp=0xc4200c1ea8 sp=0xc4200c1e78 pc=0x7fa5357571a7
runtime.call32(0x0, 0x7fff085bf0e8, 0x7fff085bf180, 0x20)
	/usr/lib/go/src/runtime/asm_amd64.s:509 +0x3d fp=0xc4200c1ed8 sp=0xc4200c1ea8 pc=0x7fa535646f7d
runtime.cgocallbackg1(0x0)
	/usr/lib/go/src/runtime/cgocall.go:305 +0x1a0 fp=0xc4200c1f58 sp=0xc4200c1ed8 pc=0x7fa5355f3b00
runtime.cgocallbackg(0x0)
	/usr/lib/go/src/runtime/cgocall.go:187 +0x95 fp=0xc4200c1fc0 sp=0xc4200c1f58 pc=0x7fa5355f38c5
runtime.cgocallback_gofunc(0x0, 0x0, 0x0, 0x0)
	/usr/lib/go/src/runtime/asm_amd64.s:762 +0x9a fp=0xc4200c1fe0 sp=0xc4200c1fc0 pc=0x7fa53564858a
runtime.goexit()
	/usr/lib/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc4200c1fe8 sp=0xc4200c1fe0 pc=0x7fa535649801
[1]    4513 abort      sudo echo lol

pam_fscrypt auth module crashes login process

After adding pam_fscrypt module to pam auth config it crashes login process after providing password:

systemd[1]: Started Getty on tty2.
systemd-coredump[14940]: Process 1777 (login) of user 0 dumped core.
                                                
Stack trace of thread 1777:
#0  0x000064ee5d0edc64 n/a (pam_fscrypt.so)
#1  0x000064ee5d0d5f4b n/a (pam_fscrypt.so)
#2  0x000064ee5d0c2180 n/a (pam_fscrypt.so)
#3  0x000064ee5d0e8d7e n/a (pam_fscrypt.so)
#4  0x000064ee5d0ea082 n/a (pam_fscrypt.so)

my pam sytem-login:

#%PAM-1.0

auth       required   pam_shells.so
auth       requisite  pam_nologin.so
auth      required   pam_unix.so          try_first_pass
auth      optional  pam_permit.so
auth      required  pam_env.so
auth       optional   pam_fscrypt.so
account    required   pam_access.so
account    required   pam_nologin.so
account    include    system-auth

password   include    system-auth

session    optional   pam_keyinit.so       force revoke
session    optional   pam_fscrypt.so       drop_caches lock_policies debug
session    optional   pam_loginuid.so
session    include    system-auth
session    optional   pam_motd.so          motd=/etc/motd
session    optional   pam_mail.so          dir=/var/spool/mail standard quiet
-session    optional   pam_systemd.so
session    required   pam_env.so

my pam system-auth:

#%PAM-1.0

auth      required  pam_unix.so     try_first_pass
auth      optional  pam_permit.so
auth      required  pam_env.so

account   required  pam_unix.so
account   optional  pam_permit.so
account   required  pam_time.so

password  required  pam_unix.so     try_first_pass sha512 shadow
password  optional  pam_permit.so
password  optional  pam_fscrypt.so

session   required  pam_limits.so
session   required  pam_unix.so
session   optional  pam_permit.so

I didn't setup any passwords or protectors yet. Only run fscrypt setup

System: Archlinux
Kernel: 4.12.8

Can not move files/directories from unencrypted directory to encrypted directory

Here is my encrypted directory status:

$ fscrypt status /home/ilius/test
"/home/ilius/test" is encrypted with fscrypt.

Policy:   44f05ee076fff2d7
Unlocked: Yes

Protected with 1 protector:
PROTECTOR         LINKED  DESCRIPTION
99db526fab54e494  No      custom protector "test"
fscrypt$ fscrypt unlock /home/ilius/test
fscrypt unlock: /home/ilius/test: this file or directory is already unlocked

And here is the error I get when I try to move a file from a normal (unencrypted) directory to my encrypted directory:

mv: cannot move '../test.txt' to './test.txt': Operation not permitted

Also graphically (with Caja file manager) I get "Error moving file: Operation not permitted".

Copy works, both graphically and command line.
Also deleting the original file works (with the same user)

OS: Linux Mint 18.1 Serena
Kernel: Linux 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Tested with latest fscrypt (commit cedbe0e)

Add linux build constraints

When trying to do go get github.com/google/fscrypt on macOS, I get the following error:

# github.com/google/fscrypt/metadata
metadata/constants.go:31: undefined: unix.FS_KEY_DESCRIPTOR_SIZE
metadata/constants.go:31: const initializer 2 * unix.FS_KEY_DESCRIPTOR_SIZE is not a constant
metadata/constants.go:39: undefined: unix.FS_MAX_KEY_SIZE
metadata/policy.go:49: undefined: unix.FscryptPolicy
metadata/policy.go:74: undefined: unix.FS_POLICY_FLAGS_PAD_4
metadata/policy.go:74: undefined: unix.FS_POLICY_FLAGS_PAD_8
metadata/policy.go:75: undefined: unix.FS_POLICY_FLAGS_PAD_16
metadata/policy.go:75: undefined: unix.FS_POLICY_FLAGS_PAD_32
metadata/policy.go:88: undefined: unix.FscryptPolicy
metadata/policy.go:89: undefined: unix.FS_IOC_GET_ENCRYPTION_POLICY
metadata/policy.go:89: too many errors

To make it clearer that building will only work on linux, a build constraint should be added the the files.

Issue creating filesystem links with libblkid

fscrypt --version
Version:
0.2.0-12-gfe92c00

fscrypt encrypt --verbose /home/bbb
Reading config from "/etc/fscrypt.conf"
/home/bbb is on ext4 filesystem "/home" (/dev/sda2)
ensuring /home/bbb is an empty and readable directory
ensuring /home/bbb supports encryption and filesystem is using fscrypt
creating policy for "/home/bbb"
listing descriptors in "/home/.fscrypt/protectors"
found 0 descriptor(s)
listing descriptors in "/.fscrypt/protectors"
found 0 descriptor(s)
adding additional ProtectorOptions
Your data can be protected with one of the following sources:
1 - Your login passphrase (pam_passphrase)
2 - A custom passphrase (custom_passphrase)
3 - A raw 256-bit key (raw_key)
Enter the source number for the new protector [2 - custom_passphrase]: 1
using source: pam_passphrase
using name: 
creating login protector on "/" instead of "/home"
listing descriptors in "/.fscrypt/protectors"
found 0 descriptor(s)
KeyFunc(login protector for non-root-user, false)
Enter login passphrase for non-root-user: 
Checking login token for non-root-user
running passphrase hash for protector 1a4115c26b47168e
writing metadata to "/.fscrypt/protectors/1a4115c26b47168e"
policy on /home
        Filsystem: ext4
        Options:   [rw nosuid nodev noexec noatime stripe=32708 data=ordered]
        Device:    /dev/sda2
 protector on /
        Filsystem: ext4
        Options:   [rw noatime errors=remount-ro data=ordered]
        Device:    /dev/sda1
successfully read metadata from "/.fscrypt/protectors/1a4115c26b47168e"
blkid_evaluate_spec("/dev/sda1", <cache>) = "/dev/sda1"
blkid_get_tag_value(<cache>, UUID, /dev/sda1) = 
could not remove metadata at "/.fscrypt/protectors/1a4115c26b47168e.link"
successfully removed metadata at "/.fscrypt/protectors/1a4115c26b47168e"
fscrypt encrypt: filesystem /: no UUID: system error: cannot create filesystem link

/dev/sda1 is "/" with encryption feature disabled
/dev/sda2 is "/home" with encryption feature enabled
/home/bbb is owned by non-root-user

Directory is successfully encrypted by non-root-user using custom_passphrase method.
Directory is successfully encrypted by root while owned by root using pam_passphrase method.

I noticed that when using custom_passphrase fscrypt policy is saved in /home/.fscrypt while using pam_passphrase it tries to save it under /.fscrypt which fails.

Release tarballs don't retain version information

The Makefile contains logic to build a version string by using git describe --tags and inject it into the fscrypt build. This allows fscrypt --version to print a version string. However, the version information can't be gathered when building from the release tarballs since there's no git tree available and fscrypt --version doesn't include any version information in the output.

Passphrase is not updated when changing password with passwd

As I was looking into reproducing #93 in a VM I hit this bug.

Steps:

  1. Setup PAM unlocking for ArchLinux as described in #77. Use login password.
  2. Login as the user whose home is encrypted. Verify that the home is unlocked.
  3. Use passwd to change that user's password.
  4. Logout.
  5. Log back in, confirm that the home directory is now unreadable.

VM: https://drive.google.com/open?id=1soLFKOoFHK47d31RCn6qmJB7AORe2ysg

Uncompress (using xz, no tarball) and launch using virt-manager. Fedora 26 settings. Two users: root and qemu, both have the same password: qemu. User qemu's home is encrypted, PAM unlocking is setup.

Edit: changing the passphrase manually to match the new login password using fscrypt metadata results in a working setup again.

Document pam_passphrase weirdness

By default, protectors with type pam_passphrase have their metadata stored at the filesystem root. This is to make sure the login protectors are updated when the user's passphrase changes.

This can be unexpected as metadata is normally stored on entirely on the filesystem containing the encrypted directory. The current documentation/man pages should note how this works.

Reported as part of #50
Tracked with #10

Allow Policies to directly be unlocked with a Protector

As of right now, Policies can only be unlocked by passing OptionFunc and KeyFunc callbacks. This works in most cases. However, if there are multiple policies protected with the same protector, then the KeyFunc must be called multiple times to unlock them all.

This could be solved by adding an additional unlock method on the Policy struct.

Move `fscrypt.conf`'s format to TOML

fscrypt.conf is currently formatted as a JSON file. This is undesirable for many reasons.

During the initial design process for fscrypt, we considered using TOML as the config format (like rust does). The main reason we didn't is because TOML is less common than JSON and because the main go library had a legally problematic license.

Now that TOML is used by toolchain programs like dep and the licensing problem is fixed, TOML makes more sense.

The following will need to be completed to make this change:

  • Add support for reading fscrypt.conf as TOML
  • Start generating all new fscrypt.conf files as TOML
  • Warn users who have JSON formatted fscrypt.conf files
  • Remove support for reading a JSON config file (would need to be done before 1.0)

Document integration tests

Right now fscrypt's integration tests rely on the environment variable TEST_FILESYSTEM_ROOT being set. This variable should be set to the path of a filesystem which supports filesystem encryption, or make go (or go test) will fail.

This requirement should be documented better, or the integration tests should just not be run if TEST_FILESYSTEM_ROOT is not set.

Get spelling linter

I cannot spell. Get a linter that runs as part of the CI process that checks for spelling errors.

PAM login failure after update to bd2ca31

After updating to revision bd2ca31 my previously working fscrypt setup started failing.

Steps:

  1. Setup fscrypt (0.2.2.7.g141265f-1) + PAM unlocking using pam_fscrypt.so as described in #77 (comment)
  2. Logging in unlocks home and login succeeds (both console and GDM).
  3. Update to fscrypt 0.2.3.2.gbd2ca31-1 or 0.2.3.0.ge131cec-1 (both tested).
  4. Attempt to login results in
    a. GDM appears to succeed and then goes back to login screen (no desktop shown).
    b. Console redisplays login prompt, no shell prompt displayed.

Home directory is left in unlocked state after this, so pam_fscrypt.so is partially working. Removing all pam_fscrypt.so instances from /etc/pam.d/system-auth and /etc/pam.d/system-login results in successful login (if home directory is in unlocked state, which it is after at least one failed attempt).

Reverting to revision 141265f solves the issue and logins work again.

Non-encrypted logins do work even with pam_fscrypt.so enabled (my root home is not encrypted). Logs with debug option in all pam_fscrypt.so instances:

Look at pam_fscrypt[11273] for instance:

logs.txt

system-login.txt

system-auth.txt

Suggestion: Add documentation about passphrase hashing hardness

I'm somehow paranoid, but I have a suggestion, include argon2 iterations as an option for encrypt/decrypt folders.

The Argon2 0~20160821-1+b1 (latest) command line shows:

$ argon2
Usage: argon2 [-h] salt [-i|-d|-id] [-t iterations] [-m memory] [-p parallelism] [-l hash length] [-e|-r]
Password is read from stdin
Parameters:
salt The salt to use, at least 8 characters
-i Use Argon2i (this is the default)
-d Use Argon2d instead of Argon2i
-id Use Argon2id instead of Argon2i
-t N Sets the number of iterations to N (default = 3)
-m N Sets the memory usage of 2^N KiB (default 12)
-p N Sets parallelism to N threads (default 1)
-l N Sets hash output length to N bytes (default 32)
-e Output only encoded hash
-r Output only the raw bytes of the hash
-h Print argon2 usage

I have been using KeePass 2.36 for storing/backuping my passwords and keyfiles (I don't like it but I use for the argon2), it includes Argon2 algorithm but I can't extract anything of keyring files on the command line due to be a GUI only app (there is kpcli but is incompatible with its keyring files); it's simple to compute an approximate time by multiplying X iterations by a number to get a desired time to open such file using X threads.

I think this feature in the fscrypt could be very useful, even more with an interactive CPU time test option.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.