diff mbox

fscrypt: add a documentation file for filesystem-level encryption

Message ID 20170818194730.61575-1-ebiggers3@gmail.com
State Not Applicable
Headers show

Commit Message

Eric Biggers Aug. 18, 2017, 7:47 p.m. UTC
From: Eric Biggers <ebiggers@google.com>

Perhaps long overdue, add a documentation file for filesystem-level
encryption, a.k.a. fscrypt or fs/crypto/, to the Documentation
directory.  The new file is based loosely on the latest version of the
"EXT4 Encryption Design Document (public version)" Google Doc, but with
many improvements made, including:

- Reflect the reality that it is not specific to ext4 anymore.
- More thoroughly document the design and user-visible API/behavior.
- Replace outdated information, such as the outdated explanation of how
  encrypted filenames are hashed for indexed directories and how
  encrypted filenames are presented to userspace without the key.
  (This was changed just before release.)

For now the focus is on the design and user-visible API/behavior, not on
how to add encryption support to a filesystem --- since the internal API
is still pretty messy and any standalone documentation for it would
become outdated as things get refactored over time.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 Documentation/filesystems/fscrypt.rst | 587 ++++++++++++++++++++++++++++++++++
 Documentation/filesystems/index.rst   |  11 +
 MAINTAINERS                           |   1 +
 3 files changed, 599 insertions(+)
 create mode 100644 Documentation/filesystems/fscrypt.rst

Comments

Andreas Dilger Aug. 18, 2017, 9:06 p.m. UTC | #1
On Aug 18, 2017, at 1:47 PM, Eric Biggers <ebiggers3@gmail.com> wrote:
> +Key hierarchy
> +=============
> +
> +Master Keys
> +-----------
> +
> +Userspace should generate master keys either using a cryptographically
> +secure random number generator, e.g. by reading from ``/dev/urandom``
> +or calling getrandom(), or by using a KDF (Key Derivation Function).
> +Note that whenever a KDF is used to "stretch" a lower-entropy secret
> +such as a passphrase, it is critical that a KDF designed for this
> +purpose be used, such as scrypt, PBKDF2, or Argon2.

One minor suggestion - when generating a master key for a filesystem,
I'd think it is preferable to use /dev/random instead of /dev/urandom
to ensure there is enough entropy.

Cheers, Andreas
Theodore Ts'o Aug. 20, 2017, 2:32 a.m. UTC | #2
On Fri, Aug 18, 2017 at 03:06:52PM -0600, Andreas Dilger wrote:
> On Aug 18, 2017, at 1:47 PM, Eric Biggers <ebiggers3@gmail.com> wrote:
> > +Key hierarchy
> > +=============
> > +
> > +Master Keys
> > +-----------
> > +
> > +Userspace should generate master keys either using a cryptographically
> > +secure random number generator, e.g. by reading from ``/dev/urandom``
> > +or calling getrandom(), or by using a KDF (Key Derivation Function).
> > +Note that whenever a KDF is used to "stretch" a lower-entropy secret
> > +such as a passphrase, it is critical that a KDF designed for this
> > +purpose be used, such as scrypt, PBKDF2, or Argon2.
> 
> One minor suggestion - when generating a master key for a filesystem,
> I'd think it is preferable to use /dev/random instead of /dev/urandom
> to ensure there is enough entropy.

I would just say "use getrandom" and be done with it.  More
importantly, we probably just want to direct users to use either
https://github.com/google/fscrypt or Android key management system at
the beginning of the file.

If the readers of this documentation file need to be told how to get
good random number generators, they're very likely to make any number
of other basic security mistakes.  If people don't think the fscrypt
user program isn't user-friendly or flexible enough to encompass their
use case, it's probably better to encourage them to submit
enhancements to an existing open source key management system such as
google/fscrypt.  If we minimize the number of userspace
implementations, the easier it will be to make sure they are
appropriately audited for security issues...

						- Ted
Anand Jain Aug. 21, 2017, 1:44 p.m. UTC | #3
> +fscrypt is not guaranteed to protect confidentiality or authenticity
> +if an attacker is able to manipulate the filesystem offline prior to
> +an authorized user later accessing the filesystem.

  How does fscrypt / Android protect against Evil Maid attack. ?

Thanks, Anand
Theodore Ts'o Aug. 21, 2017, 9:02 p.m. UTC | #4
On Mon, Aug 21, 2017 at 09:44:11PM +0800, Anand Jain wrote:
> 
> 
> > +fscrypt is not guaranteed to protect confidentiality or authenticity
> > +if an attacker is able to manipulate the filesystem offline prior to
> > +an authorized user later accessing the filesystem.
> 
>  How does fscrypt / Android protect against Evil Maid attack. ?

In order to answer that question it's important to be specific about
threat model is like; exactly what powers does the Evil Maid actually
have?

One of the stronger form of the Evil Maid attack posits that the Evil
Made can remove the device from your hotel room, modify the hardware
undetectably (up to and including desoldering the flash chip so it can
be read and write directly), then replace it back to your hotel room,
wait for you to login, and then later on, steal your phone and
desolder the flash chip again.

This sort of attack is going to require a combination of hardware and
software features.  Without talking about future product features on
any specific future device being shipped by Google or any other
company --- theoretically, if the keys are stored a hardware device
which only disgorges the keys sends them directly to the in-line
crypto engine without letting the keys be visible to the Linux kernel
(or the Host CPU in any way at all), then it makes these sorts of Evil
Maid much more difficult.

Of course, if the Evil Maid can somehow insert something to tap the
communications channel between the key storage device and the
inline-crypto engine, then all bets are off.  Presumably, though, this
could be made harder; for example, by putting them on the
system-on-a-chip.

					- Ted
Eric Biggers Aug. 21, 2017, 10:33 p.m. UTC | #5
On Sat, Aug 19, 2017 at 10:32:27PM -0400, Theodore Ts'o wrote:
> On Fri, Aug 18, 2017 at 03:06:52PM -0600, Andreas Dilger wrote:
> > On Aug 18, 2017, at 1:47 PM, Eric Biggers <ebiggers3@gmail.com> wrote:
> > > +Key hierarchy
> > > +=============
> > > +
> > > +Master Keys
> > > +-----------
> > > +
> > > +Userspace should generate master keys either using a cryptographically
> > > +secure random number generator, e.g. by reading from ``/dev/urandom``
> > > +or calling getrandom(), or by using a KDF (Key Derivation Function).
> > > +Note that whenever a KDF is used to "stretch" a lower-entropy secret
> > > +such as a passphrase, it is critical that a KDF designed for this
> > > +purpose be used, such as scrypt, PBKDF2, or Argon2.
> > 
> > One minor suggestion - when generating a master key for a filesystem,
> > I'd think it is preferable to use /dev/random instead of /dev/urandom
> > to ensure there is enough entropy.
> 
> I would just say "use getrandom" and be done with it.  More
> importantly, we probably just want to direct users to use either
> https://github.com/google/fscrypt or Android key management system at
> the beginning of the file.
> 
> If the readers of this documentation file need to be told how to get
> good random number generators, they're very likely to make any number
> of other basic security mistakes.  If people don't think the fscrypt
> user program isn't user-friendly or flexible enough to encompass their
> use case, it's probably better to encourage them to submit
> enhancements to an existing open source key management system such as
> google/fscrypt.  If we minimize the number of userspace
> implementations, the easier it will be to make sure they are
> appropriately audited for security issues...
> 

Yes, the intent wasn't really to start a debate about /dev/random vs.
/dev/urandom vs. getrandom().  I'll probably just remove the text "e.g. by
reading from /dev/urandom or calling getrandom()".

I agree that we should recommend the 'fscrypt' userspace tool more strongly as
well.  I did mention it at the beginning of the document, but I didn't
explicitly say something like "use this instead of writing your own tool".

Either way, the kernel API should still be fully documented.  And part of that
is documenting that the master key needs to be a good pseudorandom key.
Otherwise I could imagine someone mistakenly thinking that the filesystem does
key stretching for them, for example.  (Yes, that person probably wouldn't read
the documentation and would screw up anyway, but we might as well try.)

Eric
Eric Biggers Aug. 21, 2017, 11:08 p.m. UTC | #6
On Mon, Aug 21, 2017 at 09:44:11PM +0800, Anand Jain wrote:
> 
> 
> >+fscrypt is not guaranteed to protect confidentiality or authenticity
> >+if an attacker is able to manipulate the filesystem offline prior to
> >+an authorized user later accessing the filesystem.
> 
>  How does fscrypt / Android protect against Evil Maid attack. ?
> 
> Thanks, Anand

As Ted mentioned, it really depends on the type of attack.

If we assume that the attacker can *only* change the contents of disk, then
there is a protection against a specific type of attack.  Android has Verified
Boot, which verifies the integrity and authenticity of the kernel and the
'system' partition: https://source.android.com/security/verifiedboot/

From there, the vold binary (which has been authenticated using dm-verity) is
able to unwrap the encryption keys (which are authenticated using AES-GCM), then
check that the encrypted directories have the correct encryption policies.  The
filesystem then enforces the one-policy-per-tree constraint, as described in my
proposed documentation:

    Except for those special files, it is forbidden to have unencrypted
    files, or files encrypted with a different encryption policy, in an
    encrypted directory tree.  Attempts to link or rename such a file into
    an encrypted directory will fail with EPERM.  This is also enforced
    during ->lookup() to provide limited protection against offline
    attacks that try to disable or downgrade encryption in known locations
    where applications may later write sensitive data.

So on Android, an "Evil Maid" attacker cannot simply replace an encrypted
directory with an unencrypted one, causing a program to write unencrypted files
to that directory.

_However_, an "Evil Maid" attacker can probably still do other, perhaps much
more effective attacks --- e.g. installing a hardware "key logger", or perhaps
installing a binary into /data in such a way that it gets auto-executed and
compromises the system after the user logs in.  Or they could attack the actual
file contents encryption which is not authenticated.  Or they could mess around
with filesystem metadata on the userdata partition, which is neither encrypted
nor authenticated.

I suppose that dm-integrity could be used to protect against some of those
attacks, but of course it would not protect against hardware key loggers, etc.

Eric
Anand Jain Aug. 22, 2017, 2:22 a.m. UTC | #7
>>> +fscrypt is not guaranteed to protect confidentiality or authenticity
>>> +if an attacker is able to manipulate the filesystem offline prior to
>>> +an authorized user later accessing the filesystem.
>>
>>   How does fscrypt / Android protect against Evil Maid attack. ?

> _However_, an "Evil Maid" attacker can probably still do other, perhaps much
> more effective attacks --- e.g.
::
>.  Or they could attack the actual
> file contents encryption which is not authenticated.  Or they could mess around
> with filesystem metadata on the userdata partition, which is neither encrypted
> nor authenticated.

   In specific, the scenario I had in mind was the above threat.

> I suppose that dm-integrity could be used to protect against some of those
> attacks, but of course it would not protect against hardware key loggers, etc.

   OK.


   I think AE is the only good solution for this, File-name encryption 
at this stage won't solve any kind of Evil Maid attack, (as it was 
quoted somewhere else in ML).


  Further, below,  is define but not used.
-----
  #define FS_AES_256_GCM_KEY_SIZE		32
-----


Thanks, Anand
Anand Jain Aug. 22, 2017, 2:22 a.m. UTC | #8
Hi Eric,

   How about a section on the threat model specific to the file-name ?

   (Sorry if I am missing something).

Thanks, Anand
Eric Biggers Aug. 22, 2017, 2:55 a.m. UTC | #9
On Tue, Aug 22, 2017 at 10:22:30AM +0800, Anand Jain wrote:
> 
> Hi Eric,
> 
>   How about a section on the threat model specific to the file-name ?
> 
>   (Sorry if I am missing something).
> 
> Thanks, Anand

It's already mentioned that filenames are encrypted: "fscrypt protects the
confidentiality of file contents and filenames in the event of a single
point-in-time permanent offline compromise of the block device content."
There's not much more to it than that; all the other points in the "Threat
model" section (offline manipulations, timing attacks, access control, key
eviction, etc.) are essentially the same between contents and filenames
encryption.

Eric
Eric Biggers Aug. 22, 2017, 3:07 a.m. UTC | #10
On Tue, Aug 22, 2017 at 10:22:13AM +0800, Anand Jain wrote:
> 
> 
> 
> > > > +fscrypt is not guaranteed to protect confidentiality or authenticity
> > > > +if an attacker is able to manipulate the filesystem offline prior to
> > > > +an authorized user later accessing the filesystem.
> > > 
> > >   How does fscrypt / Android protect against Evil Maid attack. ?
> 
> > _However_, an "Evil Maid" attacker can probably still do other, perhaps much
> > more effective attacks --- e.g.
> ::
> > .  Or they could attack the actual
> > file contents encryption which is not authenticated.  Or they could mess around
> > with filesystem metadata on the userdata partition, which is neither encrypted
> > nor authenticated.
> 
>   In specific, the scenario I had in mind was the above threat.
> 
> > I suppose that dm-integrity could be used to protect against some of those
> > attacks, but of course it would not protect against hardware key loggers, etc.
> 
>   OK.
> 
> 
>   I think AE is the only good solution for this, File-name encryption at
> this stage won't solve any kind of Evil Maid attack, (as it was quoted
> somewhere else in ML).
> 
> 
>  Further, below,  is define but not used.
> -----
>  #define FS_AES_256_GCM_KEY_SIZE		32
> -----
> 

Yes, authenticated encryption with AES-256-GCM was in an older version of the
ext4 encryption design document.  But unfortunately it was never really thought
through.  The primary problem, even ignoring rollback protection, is that there
is nowhere to store the per-block metadata (GCM authentication tag and IV) *and*
have it updated atomicly with the block contents.  Recently, dm-integrity solves
this at the block device layer, but it uses data journaling which is very
inefficient.  This maybe could be implemented more efficiently on a COW
filesystem like BTRFS.  But even after that, another problem is that
authenticated encryption of file contents only would not stop an attacker from
swapping around blocks, files, directories, or creating links, etc.

Eric
Theodore Ts'o Aug. 22, 2017, 3:07 a.m. UTC | #11
On Tue, Aug 22, 2017 at 10:22:13AM +0800, Anand Jain wrote:
> 
>   I think AE is the only good solution for this, File-name encryption at
> this stage won't solve any kind of Evil Maid attack, (as it was quoted
> somewhere else in ML).

AE doesn't help at all against the Evil Maid attack, since the Evil
Maid is trying get the user's keying material, and what kind of
encryption you are using is pretty much irrelevant.

The typical attack (where the user's keys are available to the host
CPU) involves compromising the system software --- and system software
is public (everyone can get a copy of the Android system image for a
particular device), so encryption is pointless.  That's why the system
image is protected using dm-verity, which provides data integrity, but
not confidentiality.

The bootloader will protect against installing a new system image
unless you have the private key of the handset manufacturer to sign
said system image.  But the Evil Maid can carry out a "chip off"
attack, where flash chip is desoldered and the system image, and the
dm-verity information can be written directly without the bootloader
being able to prevent it.

This is why using AE isn't going to help you.  Sure, the Evil Maid
could try to diddle directories and use complicated crypto attacks.
But why bother when they can just simply steal the user's keys, at
which point all the AE in the world doesn't help a whit.

Cheers,

						- Ted
Anand Jain Aug. 22, 2017, 3:33 p.m. UTC | #12
On 08/22/2017 10:55 AM, Eric Biggers wrote:
> On Tue, Aug 22, 2017 at 10:22:30AM +0800, Anand Jain wrote:
>>
>> Hi Eric,
>>
>>    How about a section on the threat model specific to the file-name ?
>>
>>    (Sorry if I am missing something).
>>
>> Thanks, Anand
> 
> It's already mentioned that filenames are encrypted: "fscrypt protects the
> confidentiality of file contents and filenames in the event of a single
> point-in-time permanent offline compromise of the block device content."
> There's not much more to it than that; all the other points in the "Threat
> model" section (offline manipulations, timing attacks, access control, key
> eviction, etc.) are essentially the same between contents and filenames
> encryption.

  Do you think if application does not keep the sensitive information in 
the file-name, would that remove the file-name from the list of items 
that should be protected ?

Thanks, Anand
Anand Jain Aug. 22, 2017, 3:35 p.m. UTC | #13
>>>>> +fscrypt is not guaranteed to protect confidentiality or authenticity
>>>>> +if an attacker is able to manipulate the filesystem offline prior to
>>>>> +an authorized user later accessing the filesystem.
>>>>
>>>>    How does fscrypt / Android protect against Evil Maid attack. ?
>>
>>> _However_, an "Evil Maid" attacker can probably still do other, perhaps much
>>> more effective attacks --- e.g.
>> ::
>>> .  Or they could attack the actual
>>> file contents encryption which is not authenticated.  Or they could mess around
>>> with filesystem metadata on the userdata partition, which is neither encrypted
>>> nor authenticated.
>>
>>    In specific, the scenario I had in mind was the above threat.
>>
>>> I suppose that dm-integrity could be used to protect against some of those
>>> attacks, but of course it would not protect against hardware key loggers, etc.
>>
>>    OK.
>>
>>
>>    I think AE is the only good solution for this, File-name encryption at
>> this stage won't solve any kind of Evil Maid attack, (as it was quoted
>> somewhere else in ML).
>>
>>
>>   Further, below,  is define but not used.
>> -----
>>   #define FS_AES_256_GCM_KEY_SIZE		32
>> -----
>>
> 
> Yes, authenticated encryption with AES-256-GCM was in an older version of the
> ext4 encryption design document.  But unfortunately it was never really thought
> through. The primary problem, even ignoring rollback protection, is that there
> is nowhere to store the per-block metadata (GCM authentication tag and IV) *and*
> have it updated atomicly with the block contents.  Recently, dm-integrity solves
> this at the block device layer, but it uses data journaling which is very
> inefficient.  This maybe could be implemented more efficiently on a COW
> filesystem like BTRFS.  But even after that, another problem is that
> authenticated encryption of file contents only would not stop an attacker from
> swapping around blocks, files, directories, or creating links, etc.


  Some of the problems to be solved in this area are quite interesting 
and challenging and IMO BTRFS fits nicely. Per extent AE for BTRFS is 
drafted, it needs scrutiny and constructive feedback.

Thanks, Anand


> Eric
>
Eric Biggers Aug. 22, 2017, 5:07 p.m. UTC | #14
On Tue, Aug 22, 2017 at 11:33:51PM +0800, Anand Jain wrote:
> 
> 
> On 08/22/2017 10:55 AM, Eric Biggers wrote:
> >On Tue, Aug 22, 2017 at 10:22:30AM +0800, Anand Jain wrote:
> >>
> >>Hi Eric,
> >>
> >>   How about a section on the threat model specific to the file-name ?
> >>
> >>   (Sorry if I am missing something).
> >>
> >>Thanks, Anand
> >
> >It's already mentioned that filenames are encrypted: "fscrypt protects the
> >confidentiality of file contents and filenames in the event of a single
> >point-in-time permanent offline compromise of the block device content."
> >There's not much more to it than that; all the other points in the "Threat
> >model" section (offline manipulations, timing attacks, access control, key
> >eviction, etc.) are essentially the same between contents and filenames
> >encryption.
> 
>  Do you think if application does not keep the sensitive information
> in the file-name, would that remove the file-name from the list of
> items that should be protected ?
> 

If *no* applications care whether the filenames are encrypted or not, sure.  But
are you absolutely sure that no applications care?  How do you know?  And what
is the advantage of not encrypting the filenames anyway?  It is better to
encrypt by default.

Eric
Eric Biggers Aug. 22, 2017, 5:36 p.m. UTC | #15
On Tue, Aug 22, 2017 at 11:35:20PM +0800, Anand Jain wrote:
> >>
> >>   I think AE is the only good solution for this, File-name encryption at
> >>this stage won't solve any kind of Evil Maid attack, (as it was quoted
> >>somewhere else in ML).
> >>
> >>
> >>  Further, below,  is define but not used.
> >>-----
> >>  #define FS_AES_256_GCM_KEY_SIZE		32
> >>-----
> >>
> >
> >Yes, authenticated encryption with AES-256-GCM was in an older version of the
> >ext4 encryption design document.  But unfortunately it was never really thought
> >through. The primary problem, even ignoring rollback protection, is that there
> >is nowhere to store the per-block metadata (GCM authentication tag and IV) *and*
> >have it updated atomicly with the block contents.  Recently, dm-integrity solves
> >this at the block device layer, but it uses data journaling which is very
> >inefficient.  This maybe could be implemented more efficiently on a COW
> >filesystem like BTRFS.  But even after that, another problem is that
> >authenticated encryption of file contents only would not stop an attacker from
> >swapping around blocks, files, directories, or creating links, etc.
> 
> 
>  Some of the problems to be solved in this area are quite
> interesting and challenging and IMO BTRFS fits nicely. Per extent AE
> for BTRFS is drafted, it needs scrutiny and constructive feedback.
> 
> Thanks, Anand
> 
> 
> >Eric
> >

Where is the code?  Is there a design document, and it is it readable by people
not as familiar with btrfs?  Is the API compatible with ext4, f2fs, and ubifs?

Eric
Anand Jain Aug. 28, 2017, 12:18 p.m. UTC | #16
On 08/23/2017 01:07 AM, Eric Biggers wrote:
> On Tue, Aug 22, 2017 at 11:33:51PM +0800, Anand Jain wrote:
>>
>>
>> On 08/22/2017 10:55 AM, Eric Biggers wrote:
>>> On Tue, Aug 22, 2017 at 10:22:30AM +0800, Anand Jain wrote:
>>>>
>>>> Hi Eric,
>>>>
>>>>    How about a section on the threat model specific to the file-name ?
>>>>
>>>>    (Sorry if I am missing something).
>>>>
>>>> Thanks, Anand
>>>
>>> It's already mentioned that filenames are encrypted: "fscrypt protects the
>>> confidentiality of file contents and filenames in the event of a single
>>> point-in-time permanent offline compromise of the block device content."
>>> There's not much more to it than that; all the other points in the "Threat
>>> model" section (offline manipulations, timing attacks, access control, key
>>> eviction, etc.) are essentially the same between contents and filenames
>>> encryption.
>>
>>   Do you think if application does not keep the sensitive information
>> in the file-name, would that remove the file-name from the list of
>> items that should be protected ?
>>
> 
> If *no* applications care whether the filenames are encrypted or not, sure.
> But are you absolutely sure that no applications care?  How do you know?  And what
> is the advantage of not encrypting the filenames anyway?  It is better to
> encrypt by default.
> 
> Eric

  (sorry for the delay in reply due to my vacation).

  It all depends on the use case, Android is one such use case. Some 
data center use a known set of application. Again it all depends on the 
use case.

  File-name is a kind of File-system semantic and altering based on the 
on the user key context does not guarantee the system will be compatible 
with all their legacy applications.

  Also a section on backup and restore in this doc will be a good idea. 
As I think that will be affected IMO. And needing to have the user 
master key to restore encrypted file isn't practical in some data center 
multi tenanted solutions. Albeit it may work in some cases but hard to 
generalize.


Thanks, Anand
Anand Jain Aug. 28, 2017, 12:18 p.m. UTC | #17
On 08/23/2017 01:36 AM, Eric Biggers wrote:
> On Tue, Aug 22, 2017 at 11:35:20PM +0800, Anand Jain wrote:
>>>>
>>>>    I think AE is the only good solution for this, File-name encryption at
>>>> this stage won't solve any kind of Evil Maid attack, (as it was quoted
>>>> somewhere else in ML).
>>>>
>>>>
>>>>   Further, below,  is define but not used.
>>>> -----
>>>>   #define FS_AES_256_GCM_KEY_SIZE		32
>>>> -----
>>>>
>>>
>>> Yes, authenticated encryption with AES-256-GCM was in an older version of the
>>> ext4 encryption design document.  But unfortunately it was never really thought
>>> through. The primary problem, even ignoring rollback protection, is that there
>>> is nowhere to store the per-block metadata (GCM authentication tag and IV) *and*
>>> have it updated atomicly with the block contents.  Recently, dm-integrity solves
>>> this at the block device layer, but it uses data journaling which is very
>>> inefficient.  This maybe could be implemented more efficiently on a COW
>>> filesystem like BTRFS.  But even after that, another problem is that
>>> authenticated encryption of file contents only would not stop an attacker from
>>> swapping around blocks, files, directories, or creating links, etc.
>>
>>
>>   Some of the problems to be solved in this area are quite
>> interesting and challenging and IMO BTRFS fits nicely. Per extent AE
>> for BTRFS is drafted, it needs scrutiny and constructive feedback.
>>
>> Thanks, Anand
>>
>>
>>> Eric
>>>
> 
> Where is the code?  Is there a design document, and it is it readable by people
> not as familiar with btrfs?  Is the API compatible with ext4, f2fs, and ubifs?
> 
> Eric

  (sorry for the delay in replay due to my vacation).

  Eric, No code yet, proposed encryption method is seeking review. Link 
sent to you.

Thanks, Anand
Theodore Ts'o Aug. 28, 2017, 2:22 p.m. UTC | #18
On Mon, Aug 28, 2017 at 08:18:46PM +0800, Anand Jain wrote:
> > If *no* applications care whether the filenames are encrypted or not, sure.
> > But are you absolutely sure that no applications care?  How do you know?  And what
> > is the advantage of not encrypting the filenames anyway?  It is better to
> > encrypt by default.
> > 
>  File-name is a kind of File-system semantic and altering based on the on
> the user key context does not guarantee the system will be compatible with
> all their legacy applications.

In theory we could make it optional whether or not file names are
encrypted.  But that means extra complexity, and extra complexity
means potential bugs and vulnerabilities --- both potential
implementation bugs, vulnerabilities caused by users getting confused
by how they configure the system settings.  So in general with
security systems it's better to limit the complexity to the bare
minimum.

The only case which you've come up with in terms of potential
vulnerabilities is backup and restore, and backup and restore is
complicated for a number of numbers, since you need to be able to
backup and restore not just the file name and the encrypted data
blocks, but also the encrypted per-file key.  So getting this right
will almost certainly require that the backup/restore software be
fscrypt aware.

Hence, making the encryption of the filenames optional doesn't just to
make life easier for backup/restore isn't a compelling argument, since
the backup/restore program is going to have to have special case
handling for fscrypt protected file systems *anyway*.

Cheers,

					- Ted
Anand Jain Aug. 29, 2017, 3:54 a.m. UTC | #19
>>> If *no* applications care whether the filenames are encrypted or not, sure.
>>> But are you absolutely sure that no applications care?  How do you know?  And what
>>> is the advantage of not encrypting the filenames anyway?  It is better to
>>> encrypt by default.
>>>
>>   File-name is a kind of File-system semantic and altering based on the on
>> the user key context does not guarantee the system will be compatible with
>> all their legacy applications.
> 
> In theory we could make it optional whether or not file names are
> encrypted.  But that means extra complexity, and extra complexity
> means potential bugs and vulnerabilities --- both potential
> implementation bugs, vulnerabilities caused by users getting confused
> by how they configure the system settings.  So in general with
> security systems it's better to limit the complexity to the bare
> minimum.

  That's right from the dev perspective. But for every security fix 
there is a convenience that is being sacrificed by the user. Providing a 
security fix even if there is no threat just adds pain to the 
user/solution and nothing else. Of course it all depends on the use case.


  BTRFS has an experimental fscrypt implementation[1] which does not 
include the file-name encryption part it should be included but as an 
optional since not all uses cases saves sensitive information in the 
file-name. OR even if the attacker is able to identify a file called 
secrete.txt and break it then its still points at the weakness of the 
file-data encryption. Can we say that ? apparently from the discussion 
here it seems the answer is yes.

  [1]
    Kernel: https://github.com/asj/linux-btrfs-fscryptv1



> The only case which you've come up with in terms of potential
> vulnerabilities is backup and restore, and backup and restore is
> complicated for a number of numbers, since you need to be able to
> backup and restore not just the file name and the encrypted data
> blocks, but also the encrypted per-file key.

>  So getting this right
> will almost certainly require that the backup/restore software be
> fscrypt aware.

  Not necessarily, as below..

> Hence, making the encryption of the filenames optional doesn't just to
> make life easier for backup/restore isn't a compelling argument, since
> the backup/restore program is going to have to have special case
> handling for fscrypt protected file systems *anyway*.

  fscrypt backup and restore does not work even without file-name 
encryption because the Extended Attribute needs special ioctl in the 
fscrypt (I did rise this objection before).

  But its entirely possible to create a string based encryption metadata 
which can be updated/retrieved using the legacy backup tools such as

   rsync --xattrs

  That will be a design for fscryptv2 probably..

  OR I mean to say possible optional file-name encryption is not the 
ground reason for the encrypted backup and restore challenge.

Thanks, Anand

> Cheers,
> 
> 					- Ted
Eric Biggers Aug. 31, 2017, 5:50 p.m. UTC | #20
Hi Anand,

On Mon, Aug 28, 2017 at 08:18:46PM +0800, Anand Jain wrote:
> 
> 
> On 08/23/2017 01:07 AM, Eric Biggers wrote:
> >On Tue, Aug 22, 2017 at 11:33:51PM +0800, Anand Jain wrote:
> >>
> >>
> >>On 08/22/2017 10:55 AM, Eric Biggers wrote:
> >>>On Tue, Aug 22, 2017 at 10:22:30AM +0800, Anand Jain wrote:
> >>>>
> >>>>Hi Eric,
> >>>>
> >>>>   How about a section on the threat model specific to the file-name ?
> >>>>
> >>>>   (Sorry if I am missing something).
> >>>>
> >>>>Thanks, Anand
> >>>
> >>>It's already mentioned that filenames are encrypted: "fscrypt protects the
> >>>confidentiality of file contents and filenames in the event of a single
> >>>point-in-time permanent offline compromise of the block device content."
> >>>There's not much more to it than that; all the other points in the "Threat
> >>>model" section (offline manipulations, timing attacks, access control, key
> >>>eviction, etc.) are essentially the same between contents and filenames
> >>>encryption.
> >>
> >>  Do you think if application does not keep the sensitive information
> >>in the file-name, would that remove the file-name from the list of
> >>items that should be protected ?
> >>
> >
> >If *no* applications care whether the filenames are encrypted or not, sure.
> >But are you absolutely sure that no applications care?  How do you know?  And what
> >is the advantage of not encrypting the filenames anyway?  It is better to
> >encrypt by default.
> >
> >Eric
> 
>  (sorry for the delay in reply due to my vacation).
> 
>  It all depends on the use case, Android is one such use case. Some
> data center use a known set of application. Again it all depends on
> the use case.
> 
>  File-name is a kind of File-system semantic and altering based on
> the on the user key context does not guarantee the system will be
> compatible with all their legacy applications.
> 

You really need to give more detail about why filename encryption specifically
is a problem.  What "legacy applications" is a problem for, and why?  What do
you mean by a "data center" use case?  Isn't contents encryption a "problem" for
some "legacy applications" as well?  Contents encryption changes filesystem
semantics as well.

>  Also a section on backup and restore in this doc will be a good
> idea. As I think that will be affected IMO. And needing to have the
> user master key to restore encrypted file isn't practical in some
> data center multi tenanted solutions. Albeit it may work in some
> cases but hard to generalize.
> 

The proposed documentation already mentions that there is no way to backup the
raw ciphertext currently.  I'll try to make this a bit clearer, but in any case
I am documenting the current state of things; the new documentation file is
*not* a plan for things that don't exist yet.  If/when someone proposes a
patchset which adds a backup+restore API they can propose a documentation update
along with it.

Eric
Eric Biggers Aug. 31, 2017, 6:10 p.m. UTC | #21
Hi Anand,

On Tue, Aug 29, 2017 at 11:54:47AM +0800, Anand Jain wrote:
> 
>  BTRFS has an experimental fscrypt implementation[1] which does not
> include the file-name encryption part it should be included but as
> an optional since not all uses cases saves sensitive information in
> the file-name. OR even if the attacker is able to identify a file
> called secrete.txt and break it then its still points at the
> weakness of the file-data encryption. Can we say that ? apparently
> from the discussion here it seems the answer is yes.
> 

Filenames by themselves can be sensitive information, since a filename can serve
as a strong indicator of what a file is.  For example, a filename could be used
as evidence that a person had access to a certain document.

> >Hence, making the encryption of the filenames optional doesn't just to
> >make life easier for backup/restore isn't a compelling argument, since
> >the backup/restore program is going to have to have special case
> >handling for fscrypt protected file systems *anyway*.
> 
>  fscrypt backup and restore does not work even without file-name
> encryption because the Extended Attribute needs special ioctl in the
> fscrypt (I did rise this objection before).
> 
>  But its entirely possible to create a string based encryption
> metadata which can be updated/retrieved using the legacy backup
> tools such as
> 
>   rsync --xattrs
> 
>  That will be a design for fscryptv2 probably..
> 
>  OR I mean to say possible optional file-name encryption is not the
> ground reason for the encrypted backup and restore challenge.
> 

This was already discussed.  You cannot simply add and remove the encryption
xattr from random files and directories; what happens to all the open file
descriptors, memory maps, pagecache pages, dcache entries, etc.?  Are the
existing contents and directory entries supposed to be left unencrypted, or are
they supposed to be already encrypted, or is the filesystem supposed to
automatically encrypt them when the xattr is set?  What about when the xattr is
removed?  Again, you're of course free to propose a design which takes into
account all of this and makes the argument for adding an xattr-based API, but I
haven't seen it yet.

Eric
Eric Biggers Aug. 31, 2017, 6:14 p.m. UTC | #22
On Mon, Aug 28, 2017 at 08:18:55PM +0800, Anand Jain wrote:
> 
> 
> On 08/23/2017 01:36 AM, Eric Biggers wrote:
> >On Tue, Aug 22, 2017 at 11:35:20PM +0800, Anand Jain wrote:
> >>>>
> >>>>   I think AE is the only good solution for this, File-name encryption at
> >>>>this stage won't solve any kind of Evil Maid attack, (as it was quoted
> >>>>somewhere else in ML).
> >>>>
> >>>>
> >>>>  Further, below,  is define but not used.
> >>>>-----
> >>>>  #define FS_AES_256_GCM_KEY_SIZE		32
> >>>>-----
> >>>>
> >>>
> >>>Yes, authenticated encryption with AES-256-GCM was in an older version of the
> >>>ext4 encryption design document.  But unfortunately it was never really thought
> >>>through. The primary problem, even ignoring rollback protection, is that there
> >>>is nowhere to store the per-block metadata (GCM authentication tag and IV) *and*
> >>>have it updated atomicly with the block contents.  Recently, dm-integrity solves
> >>>this at the block device layer, but it uses data journaling which is very
> >>>inefficient.  This maybe could be implemented more efficiently on a COW
> >>>filesystem like BTRFS.  But even after that, another problem is that
> >>>authenticated encryption of file contents only would not stop an attacker from
> >>>swapping around blocks, files, directories, or creating links, etc.
> >>
> >>
> >>  Some of the problems to be solved in this area are quite
> >>interesting and challenging and IMO BTRFS fits nicely. Per extent AE
> >>for BTRFS is drafted, it needs scrutiny and constructive feedback.
> >>
> >>Thanks, Anand
> >>
> >>
> >>>Eric
> >>>
> >
> >Where is the code?  Is there a design document, and it is it readable by people
> >not as familiar with btrfs?  Is the API compatible with ext4, f2fs, and ubifs?
> >
> >Eric
> 
>  (sorry for the delay in replay due to my vacation).
> 
>  Eric, No code yet, proposed encryption method is seeking review.
> Link sent to you.
> 
> Thanks, Anand

Thanks, I'll review it when I have time.  Can you please consider sending out a
public link to linux-fscrypt, linux-fsdevel, linux-btrfs, etc. so that other
people can review it too?

Eric
diff mbox

Patch

diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
new file mode 100644
index 000000000000..633d859a0ab1
--- /dev/null
+++ b/Documentation/filesystems/fscrypt.rst
@@ -0,0 +1,587 @@ 
+=====================================
+Filesystem-level encryption (fscrypt)
+=====================================
+
+Introduction
+============
+
+fscrypt is a library which filesystems can hook into to support
+transparent encryption of files and directories.
+
+Note: "fscrypt" in this document refers to the kernel-level portion,
+implemented in ``fs/crypto/``, as opposed to the userspace tool
+`fscrypt <https://github.com/google/fscrypt>`_.  This document only
+covers the kernel-level portion.  For command-line examples of how to
+use encryption, see the documentation for the userspace tool `fscrypt
+<https://github.com/google/fscrypt>`_.
+
+Unlike dm-crypt, fscrypt operates at the filesystem level rather than
+at the block device level.  This allows it to encrypt different files
+with different keys and to have unencrypted files on the same
+filesystem.  This is useful for multi-user systems where each user's
+data-at-rest needs to be cryptographically isolated from the others.
+However, except for filenames, fscrypt does not encrypt filesystem
+metadata.
+
+Unlike eCryptfs, which is a stacked filesystem, fscrypt is integrated
+directly into supported filesystems --- currently ext4, F2FS, and
+UBIFS.  This allows encrypted files to be read and written without
+caching both the decrypted and encrypted pages in the pagecache,
+thereby halving the memory used and bringing it in line with
+unencrypted files.  Similarly, half as many dentries and inodes are
+needed.  eCryptfs also limits filenames to 143 bytes, causing
+application compatibility issues; fscrypt allows the full 255 bytes
+(NAME_MAX).  Finally, unlike eCryptfs, the fscrypt API can be used by
+unprivileged users, with no need to mount anything.
+
+fscrypt does not support encrypting files in-place.  Instead, it
+supports marking an empty directory as encrypted.  Then, after
+userspace provides the key, all regular files, directories, and
+symbolic links created in that directory tree are transparently
+encrypted.
+
+Threat model
+============
+
+Offline attacks
+---------------
+
+Provided that userspace chooses a strong encryption key, fscrypt
+protects the confidentiality of file contents and filenames in the
+event of a single point-in-time permanent offline compromise of the
+block device content.  fscrypt does not protect the confidentiality of
+non-filename metadata, e.g. file sizes, file permissions, file
+timestamps, and extended attributes.  Also, the existence and location
+of holes (unallocated blocks which logically contain all zeroes) in
+files is not protected.
+
+fscrypt is not guaranteed to protect confidentiality or authenticity
+if an attacker is able to manipulate the filesystem offline prior to
+an authorized user later accessing the filesystem.
+
+Online attacks
+--------------
+
+fscrypt (and storage encryption in general) can only provide limited
+protection, if any at all, against online attacks.  In detail:
+
+fscrypt is only resistant to side-channel attacks, such as timing or
+electromagnetic attacks, to the extent that the underlying Linux
+Cryptographic API algorithms are.  If a vulnerable algorithm is used,
+such as a table-based implementation of AES, it may be possible for an
+attacker to mount a side channel attack against the online system.
+
+After an encryption key has been provided, fscrypt is not designed to
+hide the plaintext file contents or filenames from other users on the
+same system, regardless of the visibility of the keyring key.
+Instead, existing access control mechanisms such as file mode bits,
+POSIX ACLs, or SELinux should be used for this purpose.  Also note
+that as long as the encryption keys are *anywhere* in memory, an
+online attacker can necessarily compromise them by mounting a physical
+attack or by exploiting any kernel security vulnerability which
+provides an arbitrary memory read primitive.
+
+While it is ostensibly possible to "evict" keys from the system,
+recently accessed encrypted files will remain accessible at least
+until the filesystem is unmounted or the VFS caches are dropped, e.g.
+using ``echo 2 > /proc/sys/vm/drop_caches``.  Even after that, if the
+RAM is compromised before being powered off, it will likely still be
+possible to recover portions of the plaintext file contents, if not
+some of the encryption keys as well.  (Since Linux v4.12, all
+in-kernel keys related to fscrypt are sanitized before being freed.
+However, userspace would need to do its part as well.)
+
+Currently, fscrypt does not prevent a user from maliciously providing
+an incorrect key for another user's existing encrypted files.  A
+protection against this is planned.
+
+Key hierarchy
+=============
+
+Master Keys
+-----------
+
+Each encrypted directory tree is protected by a *master key*.  Master
+keys can be up to 64 bytes long, and must be at least as long as the
+greater of the key length needed by the contents and filenames
+encryption modes being used.  For example, if AES-256-XTS is used for
+contents encryption, the master key must be 64 bytes (512 bits).  Note
+that the XTS mode is defined to require a key twice as long as that
+required by the underlying block cipher.
+
+To "unlock" an encrypted directory tree, userspace must provide the
+appropriate master key.  There can be any number of master keys, each
+of which protects any number of directory trees on any number of
+filesystems.
+
+Userspace should generate master keys either using a cryptographically
+secure random number generator, e.g. by reading from ``/dev/urandom``
+or calling getrandom(), or by using a KDF (Key Derivation Function).
+Note that whenever a KDF is used to "stretch" a lower-entropy secret
+such as a passphrase, it is critical that a KDF designed for this
+purpose be used, such as scrypt, PBKDF2, or Argon2.
+
+Per-file keys
+-------------
+
+Master keys are not used to encrypt file contents or names directly.
+Instead, a unique key is derived for each encrypted file, including
+each regular file, directory, and symbolic link.  This has several
+advantages:
+
+- In cryptosystems, the same key material should never be used for
+  different purposes.  Using the master key as both an XTS key for
+  contents encryption and as a CTS-CBC key for filenames encryption
+  would violate this rule.
+- Per-file keys simplify the choice of IVs (Initialization Vectors)
+  for contents encryption.  Without per-file keys, to ensure IV
+  uniqueness both the inode and logical block number would need to be
+  encoded in the IVs.  This would make it impossible to renumber
+  inodes, which e.g. ``resize2fs`` can do when resizing an ext4
+  filesystem.  With per-file keys, it is sufficient to encode just the
+  logical block number in the IVs.
+- Per-file keys strengthen the encryption of filenames, where IVs are
+  reused out of necessity.  With a unique key per directory, IV reuse
+  is limited to within a single directory.
+- Per-file keys allow individual files to be securely erased simply by
+  securely erasing their keys.  (Not yet implemented.)
+
+A KDF (Key Derivation Function) is used to derive per-file keys from
+the master key.  This is done instead of wrapping a randomly-generated
+key for each file because it reduces the size of the encryption xattr,
+which for some filesystems makes the xattr more likely to fit in-line
+in the filesystem's inode table.  With a KDF, only a 16-byte nonce is
+required --- long enough to make key reuse extremely unlikely.  A
+wrapped key, on the other hand, would need to be up to 64 bytes ---
+the length of an AES-256-XTS key.  Furthermore, currently there is no
+requirement to support unlocking a file with multiple alternative
+master keys or to support rotating master keys.  Instead, the master
+keys may be wrapped in userspace, e.g. as done by the `fscrypt
+<https://github.com/google/fscrypt>`_ tool.
+
+The current KDF encrypts the master key using the 16-byte nonce as an
+AES-128-ECB key.  The output is used as the derived key.  If the
+output is longer than needed, then it is truncated to the needed
+length.  Truncation is the norm for directories and symlinks, since
+those use the CTS-CBC encryption mode which requires a key half as
+long as that required by the XTS encryption mode.
+
+Note: this KDF meets the primary security requirement, which is to
+produce unique derived keys that preserve the entropy of the master
+key, assuming that the master key is already a good pseudorandom key.
+However, it is nonstandard and has some theoretical problems such as
+being reversible, so it is generally considered to be a mistake!  It
+may be replaced with HKDF or another more standard KDF in the future.
+
+Encryption modes and usage
+==========================
+
+fscrypt allows one encryption mode to be specified for file contents
+and one encryption mode to be specified for filenames.  Different
+directory trees are permitted to use different encryption modes.
+Currently, the following pairs of encryption modes are supported:
+
+- AES-256-XTS for contents and AES-256-CTS-CBC for filenames
+- AES-128-CBC for contents and AES-128-CTS-CBC for filenames
+
+It is strongly recommended to use AES-256-XTS for contents encryption.
+AES-128-CBC was added only for low-powered embedded devices with
+crypto accelerators such as CAAM or CESA that do not support XTS.
+
+New encryption modes can be added relatively easily, without changes
+to individual filesystems.  However, authenticated encryption (AE)
+modes are not currently supported because of the difficulty of dealing
+with ciphertext expansion.
+
+For file contents, each filesystem block is encrypted independently.
+Currently, only the case where the filesystem block size is equal to
+the system's page size (usually 4096 bytes) is supported.  With the
+XTS mode of operation (recommended), the logical block number within
+the file is used as the IV.  With the CBC mode of operation (not
+recommended), ESSIV is used; specifically, the IV for CBC is the
+logical block number encrypted with AES-256, where the AES-256 key is
+the SHA-256 hash of the inode's data encryption key.
+
+For filenames, the full filename is encrypted at once.  Because of the
+requirements to retain support for efficient directory lookups and
+filenames of up to 255 bytes, a constant initialization vector (IV) is
+used.  However, each encrypted directory uses a unique key, which
+limits IV reuse to within a single directory.
+
+Since filenames are encrypted with the CTS-CBC mode of operation, the
+plaintext and ciphertext filenames need not be multiples of the AES
+block size, i.e. 16 bytes.  However, the minimum size that can be
+encrypted is 16 bytes, so shorter filenames are NUL-padded to 16 bytes
+before being encrypted.  In addition, to reduce leakage of filename
+lengths via their ciphertexts, all filenames are NUL-padded to the
+next 4, 8, 16, or 32-byte boundary (configurable).  32 is recommended
+since this provides the best confidentiality, at the cost of making
+directory entries consume slightly more space.  Note that since NUL
+(``\0``) is not otherwise a valid character in filenames, the padding
+will never produce duplicate plaintexts.
+
+Symbolic link targets are considered a type of filename and are
+encrypted in the same way as filenames in directory entries.  Each
+symlink also uses a unique key; hence, the hardcoded IV is not a
+problem for symlinks.
+
+User API
+========
+
+Setting an encryption policy
+----------------------------
+
+The FS_IOC_SET_ENCRYPTION_POLICY ioctl sets an encryption policy on an
+empty directory or verifies that a directory or regular file already
+has the specified encryption policy.  It takes in a pointer to a
+:c:type:`struct fscrypt_policy`, defined as follows::
+
+    #define FS_KEY_DESCRIPTOR_SIZE  8
+
+    struct fscrypt_policy {
+            __u8 version;
+            __u8 contents_encryption_mode;
+            __u8 filenames_encryption_mode;
+            __u8 flags;
+            __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+    };
+
+This structure must be initialized as follows:
+
+- ``version`` must be 0.
+
+- ``contents_encryption_mode`` and ``filenames_encryption_mode`` must
+  be set to constants from ``<linux/fs.h>`` which identify the
+  encryption modes to use.  If unsure, use
+  FS_ENCRYPTION_MODE_AES_256_XTS (1) for ``contents_encryption_mode``
+  and FS_ENCRYPTION_MODE_AES_256_CTS (4) for
+  ``filenames_encryption_mode``.
+
+- ``flags`` must be set to a value from ``<linux/fs.h>`` which
+  identifies the amount of NUL-padding to use when encrypting
+  filenames.  If unsure, use FS_POLICY_FLAGS_PAD_32 (0x3).
+
+- ``master_key_descriptor`` specifies how to find the master key in
+  the keyring; see `Adding keys`_.  It is up to userspace to choose a
+  unique ``master_key_descriptor`` for each master key.  The e4crypt
+  and fscrypt tools use the first 8 bytes of
+  ``SHA-512(SHA-512(master_key))``, but this particular scheme is not
+  required.  Also, the master key need not be in the keyring yet when
+  FS_IOC_SET_ENCRYPTION_POLICY is executed.  However, it must be added
+  before any files can be created in the encrypted directory.
+
+If the file is not yet encrypted, then FS_IOC_SET_ENCRYPTION_POLICY
+verifies that the file is an empty directory.  If so, the specified
+encryption policy is assigned to the directory, turning it into an
+encrypted directory.  After that, and after providing the
+corresponding master key as described in `Adding keys`_, all regular
+files, directories (recursively), and symlinks created in the
+directory will be encrypted, inheriting the same encryption policy.
+The filenames in the directory's entries will be encrypted as well.
+
+Alternatively, if the file is already encrypted, then
+FS_IOC_SET_ENCRYPTION_POLICY validates that the specified encryption
+policy exactly matches the actual one.  If they match, then the ioctl
+returns 0.  Otherwise, it fails with EEXIST.  This works on both
+regular files and directories, including nonempty directories.
+
+Note that the ext4 filesystem does not allow the root directory to be
+encrypted, even if it is empty.  Users who want to encrypt an entire
+filesystem with one key should consider using dm-crypt instead.
+
+FS_IOC_SET_ENCRYPTION_POLICY can fail with the following errors:
+
+- ``EACCES``: the file is not owned by the process's uid, nor does the
+  process have the CAP_FOWNER capability in a namespace with the file
+  owner's uid mapped
+- ``EEXIST``: the file is already encrypted with an encryption policy
+  different from the one specified
+- ``EINVAL``: an invalid encryption policy was specified (invalid
+  version, mode(s), or flags)
+- ``ENOTDIR``: the file is unencrypted and is a regular file, not a
+  directory
+- ``ENOTEMPTY``: the file is unencrypted and is a nonempty directory
+- ``ENOTTY``: this type of filesystem does not implement encryption
+- ``EOPNOTSUPP``: the kernel was not configured with encryption
+  support for this filesystem, or the filesystem superblock has not
+  had encryption enabled on it.  (For example, to use encryption on an
+  ext4 filesystem, CONFIG_EXT4_ENCRYPTION must be enabled in the
+  kernel config, and the superblock must have had the "encrypt"
+  feature flag enabled using ``tune2fs -O encrypt`` or ``mkfs.ext4 -O
+  encrypt``.)
+- ``EPERM``: this directory may not be encrypted, e.g. because it is
+  the root directory of an ext4 filesystem
+- ``EROFS``: the filesystem is readonly
+
+Getting an encryption policy
+----------------------------
+
+The FS_IOC_GET_ENCRYPTION_POLICY ioctl retrieves the :c:type:`struct
+fscrypt_policy`, if any, for a directory or regular file.  See above
+for the struct definition.  No additional permissions are required
+beyond the ability to open the file.
+
+FS_IOC_GET_ENCRYPTION_POLICY can fail with the following errors:
+
+- ``EINVAL``: the file is encrypted, but it uses an unrecognized
+  encryption context format
+- ``ENODATA``: the file is not encrypted
+- ``ENOTTY``: this type of filesystem does not implement encryption
+- ``EOPNOTSUPP``: the kernel was not configured with encryption
+  support for this filesystem
+
+Note: if you only need to know whether a file is encrypted or not, on
+most filesystems it is also possible to use the FS_IOC_GETFLAGS ioctl
+and check for FS_ENCRYPT_FL, or to use the statx() system call and
+check for STATX_ATTR_ENCRYPTED in stx_attributes.
+
+Getting the per-filesystem salt
+-------------------------------
+
+Some filesystems, such as ext4 and F2FS, also support the deprecated
+ioctl FS_IOC_GET_ENCRYPTION_PWSALT.  This ioctl retrieves a randomly
+generated 16-byte value stored in the filesystem superblock.  This
+value is intended to used as a salt when deriving an encryption key
+from a passphrase or other low-entropy user credential.
+
+FS_IOC_GET_ENCRYPTION_PWSALT is deprecated.  Instead, prefer to
+generate and manage any needed salt(s) in userspace.
+
+Adding keys
+-----------
+
+To provide a master key, userspace must add it to an appropriate
+keyring using the add_key() system call (see:
+``Documentation/security/keys/core.rst``).  The key type must be
+"logon"; keys of this type are kept in kernel memory and cannot be
+read back by userspace.  The key description must be "fscrypt:"
+followed by the 16-character lower case hex representation of the
+``master_key_descriptor`` that was set in the encryption policy.  The
+key payload must conform to the following structure::
+
+    #define FS_MAX_KEY_SIZE 64
+
+    struct fscrypt_key {
+            u32 mode;
+            u8 raw[FS_MAX_KEY_SIZE];
+            u32 size;
+    };
+
+``mode`` is ignored; just set it to 0.  The actual key is provided in
+``raw`` with ``size`` indicating its size in bytes.  That is, the
+bytes ``raw[0..size-1]`` (inclusive) are the actual key.
+
+The key description prefix "fscrypt:" may alternatively be replaced
+with a filesystem-specific prefix such as "ext4:".  However, the
+filesystem-specific prefixes are deprecated and should not be used in
+new programs.
+
+There are several different types of keyrings in which encryption keys
+may be placed, such as a session keyring, a user session keyring, or a
+user keyring.  Each key must be placed in a keyring that is "attached"
+to all processes that might need to access files encrypted with it, in
+the sense that request_key() will find the key.  Generally, if only
+processes belonging to a specific user need to access a given
+encrypted directory and no session keyring has been installed, then
+that directory's key should be placed in that user's user session
+keyring or user keyring.  Otherwise, a session keyring should be
+installed if needed, and the key should be linked into that session
+keyring, or in a keyring linked into that session keyring.
+
+Note: introducing the complex visibility semantics of keyrings here
+was arguably a mistake --- especially given that by design, after any
+process successfully opens an encrypted file (thereby setting up the
+per-file key), possessing the keyring key is not actually required for
+any process to read/write the file until its in-memory inode is
+evicted.  In the future there probably should be a way to provide keys
+directly to the filesystem instead, which would make the intended
+semantics clearer.
+
+Access semantics
+================
+
+With the key
+------------
+
+With the encryption key, encrypted regular files, directories, and
+symlinks behave very similarly to their unencrypted counterparts ---
+after all, the encryption is intended to be transparent.  However,
+astute users may notice some differences in behavior:
+
+- Unencrypted files, or files encrypted with a different encryption
+  policy (i.e. different key, modes, or flags), cannot be renamed or
+  linked into an encrypted directory; see `Encryption policy
+  enforcement`_.  Attempts to do so will fail with EPERM.  However,
+  encrypted files can be renamed within an encrypted directory, or
+  into an unencrypted directory.
+
+- Direct I/O is not supported on encrypted files.  Attempts to use
+  direct I/O on such files will fall back to buffered I/O.
+
+- The fallocate operations FALLOC_FL_COLLAPSE_RANGE,
+  FALLOC_FL_INSERT_RANGE, and FALLOC_FL_ZERO_RANGE are not supported
+  on encrypted files and will fail with EOPNOTSUPP.
+
+- Online defragmentation of encrypted files is not supported.  The
+  EXT4_IOC_MOVE_EXT and F2FS_IOC_MOVE_RANGE ioctls will fail with
+  EOPNOTSUPP.
+
+- The ext4 filesystem does not support data journaling with encrypted
+  regular files.  It will fall back to ordered data mode instead.
+
+- DAX (Direct Access) is not supported on encrypted files.
+
+- The st_size of an encrypted symlink will not necessarily give the
+  length of the symlink target as required by POSIX.  It will actually
+  give the length of the ciphertext, which may be slightly longer than
+  the plaintext due to the NUL-padding.
+
+Note that mmap *is* supported.  This is possible because the pagecache
+for an encrypted file contains the plaintext, not the ciphertext.
+
+Without the key
+---------------
+
+Some filesystem operations may be performed on encrypted regular
+files, directories, and symlinks even before their encryption key has
+been provided:
+
+- File metadata may be read, e.g. using stat().
+
+- Directories may be listed, in which case the filenames will be
+  listed in an encoded form derived from their ciphertext.  The
+  current encoding algorithm is described in `Filename hashing and
+  encoding`_.  The algorithm is subject to change, but it is
+  guaranteed that the presented filenames will be no longer than
+  NAME_MAX bytes, will not contain the ``/`` or ``\0`` characters, and
+  will uniquely identify directory entries.
+
+  The ``.`` and ``..`` directory entries are special.  They are always
+  present and are not encrypted or encoded.
+
+- Files may be deleted.  That is, nondirectory files may be deleted
+  with unlink() as usual, and empty directories may be deleted with
+  rmdir() as usual.  Therefore, ``rm`` and ``rm -r`` will work as
+  expected.
+
+- Symlink targets may be read and followed, but they will be presented
+  in encrypted form, similar to filenames in directories.  Hence, they
+  are unlikely to point to anywhere useful.
+
+Without the key, regular files cannot be opened or truncated.
+Attempts to do so will fail with ENOKEY.  This implies that any
+regular file operations that require a file descriptor, such as
+read(), write(), mmap(), fallocate(), and ioctl(), are also forbidden.
+Note that currently there is no way to read or back up raw encrypted
+contents at the file level.
+
+Also without the key, files of any type (including directories) cannot
+be created or linked into an encrypted directory, nor can a name in an
+encrypted directory be the source or target of a rename, nor can an
+O_TMPFILE temporary file be created in an encrypted directory.  All
+such operations will fail with ENOKEY.
+
+Encryption policy enforcement
+=============================
+
+After an encryption policy has been set on a directory, all regular
+files, directories, and symbolic links created in that directory
+(recursively) will inherit that encryption policy.  Special files ---
+that is, named pipes, device nodes, and UNIX domain sockets --- will
+not be encrypted.
+
+Except for those special files, it is forbidden to have unencrypted
+files, or files encrypted with a different encryption policy, in an
+encrypted directory tree.  Attempts to link or rename such a file into
+an encrypted directory will fail with EPERM.  This is also enforced
+during ->lookup() to provide limited protection against offline
+attacks that try to disable or downgrade encryption in known locations
+where applications may later write sensitive data.
+
+Implementation details
+======================
+
+Encryption context
+------------------
+
+An encryption policy is represented on-disk by a :c:type:`struct
+fscrypt_context`.  It is up to individual filesystems to decide where
+to store it, but normally it would be stored in a hidden extended
+attribute.  It should *not* be exposed by the xattr-related system
+calls such as getxattr().  The struct is defined as follows::
+
+    #define FS_KEY_DESCRIPTOR_SIZE  8
+    #define FS_KEY_DERIVATION_NONCE_SIZE 16
+
+    struct fscrypt_context {
+            u8 format;
+            u8 contents_encryption_mode;
+            u8 filenames_encryption_mode;
+            u8 flags;
+            u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
+            u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
+    };
+
+Note that :c:type:`struct fscrypt_context` contains the same
+information as :c:type:`struct fscrypt_policy` (see `Setting an
+encryption policy`_), except that :c:type:`struct fscrypt_context`
+also contains a nonce.  The nonce is randomly generated by the kernel
+and is used to derive the inode's encryption key as described in
+`Per-file keys`_.
+
+Data path changes
+-----------------
+
+For the read path (->readpage()) of regular files, filesystems can
+read the ciphertext into the page cache and decrypt it in-place.  The
+page lock must be held until decryption has finished, to prevent the
+page from becoming visible to userspace prematurely.
+
+For the write path (->writepage()) of regular files, filesystems
+cannot encrypt data in-place in the page cache, since the cached
+plaintext must be preserved.  Instead, filesystems must encrypt into a
+temporary buffer or "bounce page", then write out the temporary
+buffer.  Some filesystems, such as UBIFS, already use temporary
+buffers regardless of encryption.  Other filesystems, such as ext4 and
+F2FS, have to allocate bounce pages specially for encryption.
+
+Filename hashing and encoding
+-----------------------------
+
+Modern filesystems accelerate directory lookups by using indexed
+directories.  An indexed directory is organized as a tree keyed by
+filename hashes.  When a ->lookup() is requested, the filesystem
+normally hashes the filename being looked up so that it can quickly
+find the corresponding directory entry, if any.
+
+With encryption, lookups must be supported and efficient both with and
+without the encryption key.  Clearly, it would not work to hash the
+plaintext filenames, since the plaintext filenames are unavailable
+without the key.  (Hashing the plaintext filenames would also make it
+impossible for the filesystem's fsck tool to optimize encrypted
+directories.)  Instead, filesystems hash the ciphertext filenames,
+i.e. the bytes actually stored on-disk in the directory entries.  When
+asked to do a ->lookup() with the key, the filesystem just encrypts
+the user-supplied name to get the ciphertext.
+
+Lookups without the key are more complicated.  The raw ciphertext may
+contain the ``\0`` and ``/`` characters, which are illegal in
+filenames.  Therefore, readdir() must base64-encode the ciphertext for
+presentation.  For most filenames, this works fine; on ->lookup(), the
+filesystem just base64-decodes the user-supplied name to get back to
+the raw ciphertext.
+
+However, for very long filenames, base64 encoding would cause the
+filename length to exceed NAME_MAX.  To prevent this, readdir()
+actually presents long filenames in an abbreviated form which encodes
+a strong "hash" of the ciphertext filename, along with the optional
+filesystem-specific hash(es) needed for directory lookups.  This
+allows the filesystem to still, with a high degree of confidence, map
+the filename given in ->lookup() back to a particular directory entry
+that was previously listed by readdir().  See :c:type:`struct
+fscrypt_digested_name` in the source for more details.
+
+Note that the precise way that filenames are presented to userspace
+without the key is subject to change in the future.  It is only meant
+as a way to temporarily present valid filenames so that commands like
+``rm -r`` work as expected on encrypted directories.
diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst
index 256e10eedba4..53b89d0edc15 100644
--- a/Documentation/filesystems/index.rst
+++ b/Documentation/filesystems/index.rst
@@ -315,3 +315,14 @@  exported for use by modules.
    :internal:
 
 .. kernel-doc:: fs/pipe.c
+
+Encryption API
+==============
+
+A library which filesystems can hook into to support transparent
+encryption of files and directories.
+
+.. toctree::
+    :maxdepth: 2
+
+    fscrypt
diff --git a/MAINTAINERS b/MAINTAINERS
index 6f7721d1634c..806748e4942c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5558,6 +5558,7 @@  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tytso/fscrypt.git
 S:	Supported
 F:	fs/crypto/
 F:	include/linux/fscrypt*.h
+F:	Documentation/filesystems/fscrypt.rst
 
 FUJITSU FR-V (FRV) PORT
 S:	Orphan