1. 07 11月, 2019 2 次提交
    • E
      fscrypt: add support for IV_INO_LBLK_64 policies · b103fb76
      Eric Biggers 提交于
      Inline encryption hardware compliant with the UFS v2.1 standard or with
      the upcoming version of the eMMC standard has the following properties:
      
      (1) Per I/O request, the encryption key is specified by a previously
          loaded keyslot.  There might be only a small number of keyslots.
      
      (2) Per I/O request, the starting IV is specified by a 64-bit "data unit
          number" (DUN).  IV bits 64-127 are assumed to be 0.  The hardware
          automatically increments the DUN for each "data unit" of
          configurable size in the request, e.g. for each filesystem block.
      
      Property (1) makes it inefficient to use the traditional fscrypt
      per-file keys.  Property (2) precludes the use of the existing
      DIRECT_KEY fscrypt policy flag, which needs at least 192 IV bits.
      
      Therefore, add a new fscrypt policy flag IV_INO_LBLK_64 which causes the
      encryption to modified as follows:
      
      - The encryption keys are derived from the master key, encryption mode
        number, and filesystem UUID.
      
      - The IVs are chosen as (inode_number << 32) | file_logical_block_num.
        For filenames encryption, file_logical_block_num is 0.
      
      Since the file nonces aren't used in the key derivation, many files may
      share the same encryption key.  This is much more efficient on the
      target hardware.  Including the inode number in the IVs and mixing the
      filesystem UUID into the keys ensures that data in different files is
      nevertheless still encrypted differently.
      
      Additionally, limiting the inode and block numbers to 32 bits and
      placing the block number in the low bits maintains compatibility with
      the 64-bit DUN convention (property (2) above).
      
      Since this scheme assumes that inode numbers are stable (which may
      preclude filesystem shrinking) and that inode and file logical block
      numbers are at most 32-bit, IV_INO_LBLK_64 will only be allowed on
      filesystems that meet these constraints.  These are acceptable
      limitations for the cases where this format would actually be used.
      
      Note that IV_INO_LBLK_64 is an on-disk format, not an implementation.
      This patch just adds support for it using the existing filesystem layer
      encryption.  A later patch will add support for inline encryption.
      Reviewed-by: NPaul Crowley <paulcrowley@google.com>
      Co-developed-by: NSatya Tangirala <satyat@google.com>
      Signed-off-by: NSatya Tangirala <satyat@google.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      b103fb76
    • E
      fscrypt: avoid data race on fscrypt_mode::logged_impl_name · ff73c2c0
      Eric Biggers 提交于
      The access to logged_impl_name is technically a data race, which tools
      like KCSAN could complain about in the future.  See:
      https://github.com/google/ktsan/wiki/READ_ONCE-and-WRITE_ONCE
      
      Fix by using xchg(), which also ensures that only one thread does the
      logging.
      
      This also required switching from bool to int, to avoid a build error on
      the RISC-V architecture which doesn't implement xchg on bytes.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      ff73c2c0
  2. 22 10月, 2019 2 次提交
    • E
      fscrypt: zeroize fscrypt_info before freeing · 6f99756d
      Eric Biggers 提交于
      memset the struct fscrypt_info to zero before freeing.  This isn't
      really needed currently, since there's no secret key directly in the
      fscrypt_info.  But there's a decent chance that someone will add such a
      field in the future, e.g. in order to use an API that takes a raw key
      such as siphash().  So it's good to do this as a hardening measure.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      6f99756d
    • E
      fscrypt: invoke crypto API for ESSIV handling · 4006d799
      Eric Biggers 提交于
      Instead of open-coding the calculations for ESSIV handling, use an ESSIV
      skcipher which does all of this under the hood.  ESSIV was added to the
      crypto API in v5.4.
      
      This is based on a patch from Ard Biesheuvel, but reworked to apply
      after all the fscrypt changes that went into v5.4.
      
      Tested with 'kvm-xfstests -c ext4,f2fs -g encrypt', including the
      ciphertext verification tests for v1 and v2 encryption policies.
      
      Originally-from: Ard Biesheuvel <ard.biesheuvel@linaro.org>
      Acked-by: NArd Biesheuvel <ard.biesheuvel@linaro.org>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      4006d799
  3. 13 8月, 2019 15 次提交
    • E
      fscrypt: allow unprivileged users to add/remove keys for v2 policies · 23c688b5
      Eric Biggers 提交于
      Allow the FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY
      ioctls to be used by non-root users to add and remove encryption keys
      from the filesystem-level crypto keyrings, subject to limitations.
      
      Motivation: while privileged fscrypt key management is sufficient for
      some users (e.g. Android and Chromium OS, where a privileged process
      manages all keys), the old API by design also allows non-root users to
      set up and use encrypted directories, and we don't want to regress on
      that.  Especially, we don't want to force users to continue using the
      old API, running into the visibility mismatch between files and keyrings
      and being unable to "lock" encrypted directories.
      
      Intuitively, the ioctls have to be privileged since they manipulate
      filesystem-level state.  However, it's actually safe to make them
      unprivileged if we very carefully enforce some specific limitations.
      
      First, each key must be identified by a cryptographic hash so that a
      user can't add the wrong key for another user's files.  For v2
      encryption policies, we use the key_identifier for this.  v1 policies
      don't have this, so managing keys for them remains privileged.
      
      Second, each key a user adds is charged to their quota for the keyrings
      service.  Thus, a user can't exhaust memory by adding a huge number of
      keys.  By default each non-root user is allowed up to 200 keys; this can
      be changed using the existing sysctl 'kernel.keys.maxkeys'.
      
      Third, if multiple users add the same key, we keep track of those users
      of the key (of which there remains a single copy), and won't really
      remove the key, i.e. "lock" the encrypted files, until all those users
      have removed it.  This prevents denial of service attacks that would be
      possible under simpler schemes, such allowing the first user who added a
      key to remove it -- since that could be a malicious user who has
      compromised the key.  Of course, encryption keys should be kept secret,
      but the idea is that using encryption should never be *less* secure than
      not using encryption, even if your key was compromised.
      
      We tolerate that a user will be unable to really remove a key, i.e.
      unable to "lock" their encrypted files, if another user has added the
      same key.  But in a sense, this is actually a good thing because it will
      avoid providing a false notion of security where a key appears to have
      been removed when actually it's still in memory, available to any
      attacker who compromises the operating system kernel.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      23c688b5
    • E
      fscrypt: v2 encryption policy support · 5dae460c
      Eric Biggers 提交于
      Add a new fscrypt policy version, "v2".  It has the following changes
      from the original policy version, which we call "v1" (*):
      
      - Master keys (the user-provided encryption keys) are only ever used as
        input to HKDF-SHA512.  This is more flexible and less error-prone, and
        it avoids the quirks and limitations of the AES-128-ECB based KDF.
        Three classes of cryptographically isolated subkeys are defined:
      
          - Per-file keys, like used in v1 policies except for the new KDF.
      
          - Per-mode keys.  These implement the semantics of the DIRECT_KEY
            flag, which for v1 policies made the master key be used directly.
            These are also planned to be used for inline encryption when
            support for it is added.
      
          - Key identifiers (see below).
      
      - Each master key is identified by a 16-byte master_key_identifier,
        which is derived from the key itself using HKDF-SHA512.  This prevents
        users from associating the wrong key with an encrypted file or
        directory.  This was easily possible with v1 policies, which
        identified the key by an arbitrary 8-byte master_key_descriptor.
      
      - The key must be provided in the filesystem-level keyring, not in a
        process-subscribed keyring.
      
      The following UAPI additions are made:
      
      - The existing ioctl FS_IOC_SET_ENCRYPTION_POLICY can now be passed a
        fscrypt_policy_v2 to set a v2 encryption policy.  It's disambiguated
        from fscrypt_policy/fscrypt_policy_v1 by the version code prefix.
      
      - A new ioctl FS_IOC_GET_ENCRYPTION_POLICY_EX is added.  It allows
        getting the v1 or v2 encryption policy of an encrypted file or
        directory.  The existing FS_IOC_GET_ENCRYPTION_POLICY ioctl could not
        be used because it did not have a way for userspace to indicate which
        policy structure is expected.  The new ioctl includes a size field, so
        it is extensible to future fscrypt policy versions.
      
      - The ioctls FS_IOC_ADD_ENCRYPTION_KEY, FS_IOC_REMOVE_ENCRYPTION_KEY,
        and FS_IOC_GET_ENCRYPTION_KEY_STATUS now support managing keys for v2
        encryption policies.  Such keys are kept logically separate from keys
        for v1 encryption policies, and are identified by 'identifier' rather
        than by 'descriptor'.  The 'identifier' need not be provided when
        adding a key, since the kernel will calculate it anyway.
      
      This patch temporarily keeps adding/removing v2 policy keys behind the
      same permission check done for adding/removing v1 policy keys:
      capable(CAP_SYS_ADMIN).  However, the next patch will carefully take
      advantage of the cryptographically secure master_key_identifier to allow
      non-root users to add/remove v2 policy keys, thus providing a full
      replacement for v1 policies.
      
      (*) Actually, in the API fscrypt_policy::version is 0 while on-disk
          fscrypt_context::format is 1.  But I believe it makes the most sense
          to advance both to '2' to have them be in sync, and to consider the
          numbering to start at 1 except for the API quirk.
      Reviewed-by: NPaul Crowley <paulcrowley@google.com>
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      5dae460c
    • E
      fscrypt: add FS_IOC_REMOVE_ENCRYPTION_KEY ioctl · b1c0ec35
      Eric Biggers 提交于
      Add a new fscrypt ioctl, FS_IOC_REMOVE_ENCRYPTION_KEY.  This ioctl
      removes an encryption key that was added by FS_IOC_ADD_ENCRYPTION_KEY.
      It wipes the secret key itself, then "locks" the encrypted files and
      directories that had been unlocked using that key -- implemented by
      evicting the relevant dentries and inodes from the VFS caches.
      
      The problem this solves is that many fscrypt users want the ability to
      remove encryption keys, causing the corresponding encrypted directories
      to appear "locked" (presented in ciphertext form) again.  Moreover,
      users want removing an encryption key to *really* remove it, in the
      sense that the removed keys cannot be recovered even if kernel memory is
      compromised, e.g. by the exploit of a kernel security vulnerability or
      by a physical attack.  This is desirable after a user logs out of the
      system, for example.  In many cases users even already assume this to be
      the case and are surprised to hear when it's not.
      
      It is not sufficient to simply unlink the master key from the keyring
      (or to revoke or invalidate it), since the actual encryption transform
      objects are still pinned in memory by their inodes.  Therefore, to
      really remove a key we must also evict the relevant inodes.
      
      Currently one workaround is to run 'sync && echo 2 >
      /proc/sys/vm/drop_caches'.  But, that evicts all unused inodes in the
      system rather than just the inodes associated with the key being
      removed, causing severe performance problems.  Moreover, it requires
      root privileges, so regular users can't "lock" their encrypted files.
      
      Another workaround, used in Chromium OS kernels, is to add a new
      VFS-level ioctl FS_IOC_DROP_CACHE which is a more restricted version of
      drop_caches that operates on a single super_block.  It does:
      
              shrink_dcache_sb(sb);
              invalidate_inodes(sb, false);
      
      But it's still a hack.  Yet, the major users of filesystem encryption
      want this feature badly enough that they are actually using these hacks.
      
      To properly solve the problem, start maintaining a list of the inodes
      which have been "unlocked" using each master key.  Originally this
      wasn't possible because the kernel didn't keep track of in-use master
      keys at all.  But, with the ->s_master_keys keyring it is now possible.
      
      Then, add an ioctl FS_IOC_REMOVE_ENCRYPTION_KEY.  It finds the specified
      master key in ->s_master_keys, then wipes the secret key itself, which
      prevents any additional inodes from being unlocked with the key.  Then,
      it syncs the filesystem and evicts the inodes in the key's list.  The
      normal inode eviction code will free and wipe the per-file keys (in
      ->i_crypt_info).  Note that freeing ->i_crypt_info without evicting the
      inodes was also considered, but would have been racy.
      
      Some inodes may still be in use when a master key is removed, and we
      can't simply revoke random file descriptors, mmap's, etc.  Thus, the
      ioctl simply skips in-use inodes, and returns -EBUSY to indicate that
      some inodes weren't evicted.  The master key *secret* is still removed,
      but the fscrypt_master_key struct remains to keep track of the remaining
      inodes.  Userspace can then retry the ioctl to evict the remaining
      inodes.  Alternatively, if userspace adds the key again, the refreshed
      secret will be associated with the existing list of inodes so they
      remain correctly tracked for future key removals.
      
      The ioctl doesn't wipe pagecache pages.  Thus, we tolerate that after a
      kernel compromise some portions of plaintext file contents may still be
      recoverable from memory.  This can be solved by enabling page poisoning
      system-wide, which security conscious users may choose to do.  But it's
      very difficult to solve otherwise, e.g. note that plaintext file
      contents may have been read in other places than pagecache pages.
      
      Like FS_IOC_ADD_ENCRYPTION_KEY, FS_IOC_REMOVE_ENCRYPTION_KEY is
      initially restricted to privileged users only.  This is sufficient for
      some use cases, but not all.  A later patch will relax this restriction,
      but it will require introducing key hashes, among other changes.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      b1c0ec35
    • E
      fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl · 22d94f49
      Eric Biggers 提交于
      Add a new fscrypt ioctl, FS_IOC_ADD_ENCRYPTION_KEY.  This ioctl adds an
      encryption key to the filesystem's fscrypt keyring ->s_master_keys,
      making any files encrypted with that key appear "unlocked".
      
      Why we need this
      ~~~~~~~~~~~~~~~~
      
      The main problem is that the "locked/unlocked" (ciphertext/plaintext)
      status of encrypted files is global, but the fscrypt keys are not.
      fscrypt only looks for keys in the keyring(s) the process accessing the
      filesystem is subscribed to: the thread keyring, process keyring, and
      session keyring, where the session keyring may contain the user keyring.
      
      Therefore, userspace has to put fscrypt keys in the keyrings for
      individual users or sessions.  But this means that when a process with a
      different keyring tries to access encrypted files, whether they appear
      "unlocked" or not is nondeterministic.  This is because it depends on
      whether the files are currently present in the inode cache.
      
      Fixing this by consistently providing each process its own view of the
      filesystem depending on whether it has the key or not isn't feasible due
      to how the VFS caches work.  Furthermore, while sometimes users expect
      this behavior, it is misguided for two reasons.  First, it would be an
      OS-level access control mechanism largely redundant with existing access
      control mechanisms such as UNIX file permissions, ACLs, LSMs, etc.
      Encryption is actually for protecting the data at rest.
      
      Second, almost all users of fscrypt actually do need the keys to be
      global.  The largest users of fscrypt, Android and Chromium OS, achieve
      this by having PID 1 create a "session keyring" that is inherited by
      every process.  This works, but it isn't scalable because it prevents
      session keyrings from being used for any other purpose.
      
      On general-purpose Linux distros, the 'fscrypt' userspace tool [1] can't
      similarly abuse the session keyring, so to make 'sudo' work on all
      systems it has to link all the user keyrings into root's user keyring
      [2].  This is ugly and raises security concerns.  Moreover it can't make
      the keys available to system services, such as sshd trying to access the
      user's '~/.ssh' directory (see [3], [4]) or NetworkManager trying to
      read certificates from the user's home directory (see [5]); or to Docker
      containers (see [6], [7]).
      
      By having an API to add a key to the *filesystem* we'll be able to fix
      the above bugs, remove userspace workarounds, and clearly express the
      intended semantics: the locked/unlocked status of an encrypted directory
      is global, and encryption is orthogonal to OS-level access control.
      
      Why not use the add_key() syscall
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      
      We use an ioctl for this API rather than the existing add_key() system
      call because the ioctl gives us the flexibility needed to implement
      fscrypt-specific semantics that will be introduced in later patches:
      
      - Supporting key removal with the semantics such that the secret is
        removed immediately and any unused inodes using the key are evicted;
        also, the eviction of any in-use inodes can be retried.
      
      - Calculating a key-dependent cryptographic identifier and returning it
        to userspace.
      
      - Allowing keys to be added and removed by non-root users, but only keys
        for v2 encryption policies; and to prevent denial-of-service attacks,
        users can only remove keys they themselves have added, and a key is
        only really removed after all users who added it have removed it.
      
      Trying to shoehorn these semantics into the keyrings syscalls would be
      very difficult, whereas the ioctls make things much easier.
      
      However, to reuse code the implementation still uses the keyrings
      service internally.  Thus we get lockless RCU-mode key lookups without
      having to re-implement it, and the keys automatically show up in
      /proc/keys for debugging purposes.
      
      References:
      
          [1] https://github.com/google/fscrypt
          [2] https://goo.gl/55cCrI#heading=h.vf09isp98isb
          [3] https://github.com/google/fscrypt/issues/111#issuecomment-444347939
          [4] https://github.com/google/fscrypt/issues/116
          [5] https://bugs.launchpad.net/ubuntu/+source/fscrypt/+bug/1770715
          [6] https://github.com/google/fscrypt/issues/128
          [7] https://askubuntu.com/questions/1130306/cannot-run-docker-on-an-encrypted-filesystemReviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      22d94f49
    • E
      fscrypt: rename keyinfo.c to keysetup.c · feed8258
      Eric Biggers 提交于
      Rename keyinfo.c to keysetup.c since this better describes what the file
      does (sets up the key), and it matches the new file keysetup_v1.c.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      feed8258
    • E
      fscrypt: move v1 policy key setup to keysetup_v1.c · 0109ce76
      Eric Biggers 提交于
      In preparation for introducing v2 encryption policies which will find
      and derive encryption keys differently from the current v1 encryption
      policies, move the v1 policy-specific key setup code from keyinfo.c into
      keysetup_v1.c.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      0109ce76
    • E
      fscrypt: refactor key setup code in preparation for v2 policies · 3ec4f2a6
      Eric Biggers 提交于
      Do some more refactoring of the key setup code, in preparation for
      introducing a filesystem-level keyring and v2 encryption policies:
      
      - Now that ci_inode exists, don't pass around the inode unnecessarily.
      
      - Define a function setup_file_encryption_key() which handles the crypto
        key setup given an under-construction fscrypt_info.  Don't pass the
        fscrypt_context, since everything is in the fscrypt_info.
        [This will be extended for v2 policies and the fs-level keyring.]
      
      - Define a function fscrypt_set_derived_key() which sets the per-file
        key, without depending on anything specific to v1 policies.
        [This will also be used for v2 policies.]
      
      - Define a function fscrypt_setup_v1_file_key() which takes the raw
        master key, thus separating finding the key from using it.
        [This will also be used if the key is found in the fs-level keyring.]
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      3ec4f2a6
    • E
      fscrypt: rename fscrypt_master_key to fscrypt_direct_key · a828daab
      Eric Biggers 提交于
      In preparation for introducing a filesystem-level keyring which will
      contain fscrypt master keys, rename the existing 'struct
      fscrypt_master_key' to 'struct fscrypt_direct_key'.  This is the
      structure in the existing table of master keys that's maintained to
      deduplicate the crypto transforms for v1 DIRECT_KEY policies.
      
      I've chosen to keep this table as-is rather than make it automagically
      add/remove the keys to/from the filesystem-level keyring, since that
      would add a lot of extra complexity to the filesystem-level keyring.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      a828daab
    • E
      fscrypt: add ->ci_inode to fscrypt_info · 59dc6a8e
      Eric Biggers 提交于
      Add an inode back-pointer to 'struct fscrypt_info', such that
      inode->i_crypt_info->ci_inode == inode.
      
      This will be useful for:
      
      1. Evicting the inodes when a fscrypt key is removed, since we'll track
         the inodes using a given key by linking their fscrypt_infos together,
         rather than the inodes directly.  This avoids bloating 'struct inode'
         with a new list_head.
      
      2. Simplifying the per-file key setup, since the inode pointer won't
         have to be passed around everywhere just in case something goes wrong
         and it's needed for fscrypt_warn().
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      59dc6a8e
    • E
      fscrypt: use FSCRYPT_* definitions, not FS_* · 3b6df59b
      Eric Biggers 提交于
      Update fs/crypto/ to use the new names for the UAPI constants rather
      than the old names, then make the old definitions conditional on
      !__KERNEL__.
      Reviewed-by: NTheodore Ts'o <tytso@mit.edu>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      3b6df59b
    • E
      fscrypt: use ENOPKG when crypto API support missing · 29a98c1c
      Eric Biggers 提交于
      Return ENOPKG rather than ENOENT when trying to open a file that's
      encrypted using algorithms not available in the kernel's crypto API.
      
      This avoids an ambiguity, since ENOENT is also returned when the file
      doesn't exist.
      
      Note: this is the same approach I'm taking for fs-verity.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      29a98c1c
    • E
      fscrypt: improve warnings for missing crypto API support · a4d14e91
      Eric Biggers 提交于
      Users of fscrypt with non-default algorithms will encounter an error
      like the following if they fail to include the needed algorithms into
      the crypto API when configuring the kernel (as per the documentation):
      
          Error allocating 'adiantum(xchacha12,aes)' transform: -2
      
      This requires that the user figure out what the "-2" error means.
      Make it more friendly by printing a warning like the following instead:
      
          Missing crypto API support for Adiantum (API name: "adiantum(xchacha12,aes)")
      
      Also upgrade the log level for *other* errors to KERN_ERR.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      a4d14e91
    • E
      fscrypt: improve warning messages for unsupported encryption contexts · 63f668f0
      Eric Biggers 提交于
      When fs/crypto/ encounters an inode with an invalid encryption context,
      currently it prints a warning if the pair of encryption modes are
      unrecognized, but it's silent if there are other problems such as
      unsupported context size, format, or flags.  To help people debug such
      situations, add more warning messages.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      63f668f0
    • E
      fscrypt: make fscrypt_msg() take inode instead of super_block · 886da8b3
      Eric Biggers 提交于
      Most of the warning and error messages in fs/crypto/ are for situations
      related to a specific inode, not merely to a super_block.  So to make
      things easier, make fscrypt_msg() take an inode rather than a
      super_block, and make it print the inode number.
      
      Note: This is the same approach I'm taking for fsverity_msg().
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      886da8b3
    • E
      fscrypt: remove loadable module related code · 75798f85
      Eric Biggers 提交于
      Since commit 643fa961 ("fscrypt: remove filesystem specific build
      config option"), fs/crypto/ can no longer be built as a loadable module.
      Thus it no longer needs a module_exit function, nor a MODULE_LICENSE.
      So remove them, and change module_init to late_initcall.
      Reviewed-by: NChandan Rajendra <chandan@linux.ibm.com>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      75798f85
  4. 11 7月, 2019 1 次提交
  5. 28 6月, 2019 1 次提交
    • D
      keys: Replace uid/gid/perm permissions checking with an ACL · 2e12256b
      David Howells 提交于
      Replace the uid/gid/perm permissions checking on a key with an ACL to allow
      the SETATTR and SEARCH permissions to be split.  This will also allow a
      greater range of subjects to represented.
      
      ============
      WHY DO THIS?
      ============
      
      The problem is that SETATTR and SEARCH cover a slew of actions, not all of
      which should be grouped together.
      
      For SETATTR, this includes actions that are about controlling access to a
      key:
      
       (1) Changing a key's ownership.
      
       (2) Changing a key's security information.
      
       (3) Setting a keyring's restriction.
      
      And actions that are about managing a key's lifetime:
      
       (4) Setting an expiry time.
      
       (5) Revoking a key.
      
      and (proposed) managing a key as part of a cache:
      
       (6) Invalidating a key.
      
      Managing a key's lifetime doesn't really have anything to do with
      controlling access to that key.
      
      Expiry time is awkward since it's more about the lifetime of the content
      and so, in some ways goes better with WRITE permission.  It can, however,
      be set unconditionally by a process with an appropriate authorisation token
      for instantiating a key, and can also be set by the key type driver when a
      key is instantiated, so lumping it with the access-controlling actions is
      probably okay.
      
      As for SEARCH permission, that currently covers:
      
       (1) Finding keys in a keyring tree during a search.
      
       (2) Permitting keyrings to be joined.
      
       (3) Invalidation.
      
      But these don't really belong together either, since these actions really
      need to be controlled separately.
      
      Finally, there are number of special cases to do with granting the
      administrator special rights to invalidate or clear keys that I would like
      to handle with the ACL rather than key flags and special checks.
      
      
      ===============
      WHAT IS CHANGED
      ===============
      
      The SETATTR permission is split to create two new permissions:
      
       (1) SET_SECURITY - which allows the key's owner, group and ACL to be
           changed and a restriction to be placed on a keyring.
      
       (2) REVOKE - which allows a key to be revoked.
      
      The SEARCH permission is split to create:
      
       (1) SEARCH - which allows a keyring to be search and a key to be found.
      
       (2) JOIN - which allows a keyring to be joined as a session keyring.
      
       (3) INVAL - which allows a key to be invalidated.
      
      The WRITE permission is also split to create:
      
       (1) WRITE - which allows a key's content to be altered and links to be
           added, removed and replaced in a keyring.
      
       (2) CLEAR - which allows a keyring to be cleared completely.  This is
           split out to make it possible to give just this to an administrator.
      
       (3) REVOKE - see above.
      
      
      Keys acquire ACLs which consist of a series of ACEs, and all that apply are
      unioned together.  An ACE specifies a subject, such as:
      
       (*) Possessor - permitted to anyone who 'possesses' a key
       (*) Owner - permitted to the key owner
       (*) Group - permitted to the key group
       (*) Everyone - permitted to everyone
      
      Note that 'Other' has been replaced with 'Everyone' on the assumption that
      you wouldn't grant a permit to 'Other' that you wouldn't also grant to
      everyone else.
      
      Further subjects may be made available by later patches.
      
      The ACE also specifies a permissions mask.  The set of permissions is now:
      
      	VIEW		Can view the key metadata
      	READ		Can read the key content
      	WRITE		Can update/modify the key content
      	SEARCH		Can find the key by searching/requesting
      	LINK		Can make a link to the key
      	SET_SECURITY	Can change owner, ACL, expiry
      	INVAL		Can invalidate
      	REVOKE		Can revoke
      	JOIN		Can join this keyring
      	CLEAR		Can clear this keyring
      
      
      The KEYCTL_SETPERM function is then deprecated.
      
      The KEYCTL_SET_TIMEOUT function then is permitted if SET_SECURITY is set,
      or if the caller has a valid instantiation auth token.
      
      The KEYCTL_INVALIDATE function then requires INVAL.
      
      The KEYCTL_REVOKE function then requires REVOKE.
      
      The KEYCTL_JOIN_SESSION_KEYRING function then requires JOIN to join an
      existing keyring.
      
      The JOIN permission is enabled by default for session keyrings and manually
      created keyrings only.
      
      
      ======================
      BACKWARD COMPATIBILITY
      ======================
      
      To maintain backward compatibility, KEYCTL_SETPERM will translate the
      permissions mask it is given into a new ACL for a key - unless
      KEYCTL_SET_ACL has been called on that key, in which case an error will be
      returned.
      
      It will convert possessor, owner, group and other permissions into separate
      ACEs, if each portion of the mask is non-zero.
      
      SETATTR permission turns on all of INVAL, REVOKE and SET_SECURITY.  WRITE
      permission turns on WRITE, REVOKE and, if a keyring, CLEAR.  JOIN is turned
      on if a keyring is being altered.
      
      The KEYCTL_DESCRIBE function translates the ACL back into a permissions
      mask to return depending on possessor, owner, group and everyone ACEs.
      
      It will make the following mappings:
      
       (1) INVAL, JOIN -> SEARCH
      
       (2) SET_SECURITY -> SETATTR
      
       (3) REVOKE -> WRITE if SETATTR isn't already set
      
       (4) CLEAR -> WRITE
      
      Note that the value subsequently returned by KEYCTL_DESCRIBE may not match
      the value set with KEYCTL_SETATTR.
      
      
      =======
      TESTING
      =======
      
      This passes the keyutils testsuite for all but a couple of tests:
      
       (1) tests/keyctl/dh_compute/badargs: The first wrong-key-type test now
           returns EOPNOTSUPP rather than ENOKEY as READ permission isn't removed
           if the type doesn't have ->read().  You still can't actually read the
           key.
      
       (2) tests/keyctl/permitting/valid: The view-other-permissions test doesn't
           work as Other has been replaced with Everyone in the ACL.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      2e12256b
  6. 11 6月, 2019 1 次提交
  7. 25 4月, 2019 1 次提交
    • E
      crypto: shash - remove shash_desc::flags · 877b5691
      Eric Biggers 提交于
      The flags field in 'struct shash_desc' never actually does anything.
      The only ostensibly supported flag is CRYPTO_TFM_REQ_MAY_SLEEP.
      However, no shash algorithm ever sleeps, making this flag a no-op.
      
      With this being the case, inevitably some users who can't sleep wrongly
      pass MAY_SLEEP.  These would all need to be fixed if any shash algorithm
      actually started sleeping.  For example, the shash_ahash_*() functions,
      which wrap a shash algorithm with the ahash API, pass through MAY_SLEEP
      from the ahash API to the shash API.  However, the shash functions are
      called under kmap_atomic(), so actually they're assumed to never sleep.
      
      Even if it turns out that some users do need preemption points while
      hashing large buffers, we could easily provide a helper function
      crypto_shash_update_large() which divides the data into smaller chunks
      and calls crypto_shash_update() and cond_resched() for each chunk.  It's
      not necessary to have a flag in 'struct shash_desc', nor is it necessary
      to make individual shash algorithms aware of this at all.
      
      Therefore, remove shash_desc::flags, and document that the
      crypto_shash_*() functions can be called from any context.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NHerbert Xu <herbert@gondor.apana.org.au>
      877b5691
  8. 18 4月, 2019 1 次提交
    • E
      fscrypt: cache decrypted symlink target in ->i_link · 2c58d548
      Eric Biggers 提交于
      Path lookups that traverse encrypted symlink(s) are very slow because
      each encrypted symlink needs to be decrypted each time it's followed.
      This also involves dropping out of rcu-walk mode.
      
      Make encrypted symlinks faster by caching the decrypted symlink target
      in ->i_link.  The first call to fscrypt_get_symlink() sets it.  Then,
      the existing VFS path lookup code uses the non-NULL ->i_link to take the
      fast path where ->get_link() isn't called, and lookups in rcu-walk mode
      remain in rcu-walk mode.
      
      Also set ->i_link immediately when a new encrypted symlink is created.
      
      To safely free the symlink target after an RCU grace period has elapsed,
      introduce a new function fscrypt_free_inode(), and make the relevant
      filesystems call it just before actually freeing the inode.
      
      Cc: Al Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      2c58d548
  9. 17 4月, 2019 1 次提交
    • E
      fscrypt: use READ_ONCE() to access ->i_crypt_info · e37a784d
      Eric Biggers 提交于
      ->i_crypt_info starts out NULL and may later be locklessly set to a
      non-NULL value by the cmpxchg() in fscrypt_get_encryption_info().
      
      But ->i_crypt_info is used directly, which technically is incorrect.
      It's a data race, and it doesn't include the data dependency barrier
      needed to safely dereference the pointer on at least one architecture.
      
      Fix this by using READ_ONCE() instead.  Note: we don't need to use
      smp_load_acquire(), since dereferencing the pointer only requires a data
      dependency barrier, which is already included in READ_ONCE().  We also
      don't need READ_ONCE() in places where ->i_crypt_info is unconditionally
      dereferenced, since it must have already been checked.
      
      Also downgrade the cmpxchg() to cmpxchg_release(), since RELEASE
      semantics are sufficient on the write side.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      e37a784d
  10. 25 1月, 2019 1 次提交
    • E
      crypto: clarify name of WEAK_KEY request flag · 231baecd
      Eric Biggers 提交于
      CRYPTO_TFM_REQ_WEAK_KEY confuses newcomers to the crypto API because it
      sounds like it is requesting a weak key.  Actually, it is requesting
      that weak keys be forbidden (for algorithms that have the notion of
      "weak keys"; currently only DES and XTS do).
      
      Also it is only one letter away from CRYPTO_TFM_RES_WEAK_KEY, with which
      it can be easily confused.  (This in fact happened in the UX500 driver,
      though just in some debugging messages.)
      
      Therefore, make the intent clear by renaming it to
      CRYPTO_TFM_REQ_FORBID_WEAK_KEYS.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NHerbert Xu <herbert@gondor.apana.org.au>
      231baecd
  11. 06 1月, 2019 1 次提交
    • E
      fscrypt: add Adiantum support · 8094c3ce
      Eric Biggers 提交于
      Add support for the Adiantum encryption mode to fscrypt.  Adiantum is a
      tweakable, length-preserving encryption mode with security provably
      reducible to that of XChaCha12 and AES-256, subject to a security bound.
      It's also a true wide-block mode, unlike XTS.  See the paper
      "Adiantum: length-preserving encryption for entry-level processors"
      (https://eprint.iacr.org/2018/720.pdf) for more details.  Also see
      commit 059c2a4d ("crypto: adiantum - add Adiantum support").
      
      On sufficiently long messages, Adiantum's bottlenecks are XChaCha12 and
      the NH hash function.  These algorithms are fast even on processors
      without dedicated crypto instructions.  Adiantum makes it feasible to
      enable storage encryption on low-end mobile devices that lack AES
      instructions; currently such devices are unencrypted.  On ARM Cortex-A7,
      on 4096-byte messages Adiantum encryption is about 4 times faster than
      AES-256-XTS encryption; decryption is about 5 times faster.
      
      In fscrypt, Adiantum is suitable for encrypting both file contents and
      names.  With filenames, it fixes a known weakness: when two filenames in
      a directory share a common prefix of >= 16 bytes, with CTS-CBC their
      encrypted filenames share a common prefix too, leaking information.
      Adiantum does not have this problem.
      
      Since Adiantum also accepts long tweaks (IVs), it's also safe to use the
      master key directly for Adiantum encryption rather than deriving
      per-file keys, provided that the per-file nonce is included in the IVs
      and the master key isn't used for any other encryption mode.  This
      configuration saves memory and improves performance.  A new fscrypt
      policy flag is added to allow users to opt-in to this configuration.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      8094c3ce
  12. 04 9月, 2018 1 次提交
  13. 21 5月, 2018 9 次提交
    • E
      fscrypt: log the crypto algorithm implementations · e1cc40e5
      Eric Biggers 提交于
      Log the crypto algorithm driver name for each fscrypt encryption mode on
      its first use, also showing a friendly name for the mode.
      
      This will help people determine whether the expected implementations are
      being used.  In some cases we've seen people do benchmarks and reject
      using encryption for performance reasons, when in fact they used a much
      slower implementation of AES-XTS than was possible on the hardware.  It
      can make an enormous difference; e.g., AES-XTS on ARM is about 10x
      faster with the crypto extensions (AES instructions) than without.
      
      This also makes it more obvious which modes are being used, now that
      fscrypt supports multiple combinations of modes.
      
      Example messages (with default modes, on x86_64):
      
      [   35.492057] fscrypt: AES-256-CTS-CBC using implementation "cts(cbc-aes-aesni)"
      [   35.492171] fscrypt: AES-256-XTS using implementation "xts-aes-aesni"
      
      Note: algorithms can be dynamically added to the crypto API, which can
      result in different implementations being used at different times.  But
      this is rare; for most users, showing the first will be good enough.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      e1cc40e5
    • E
      fscrypt: add Speck128/256 support · 12d28f79
      Eric Biggers 提交于
      fscrypt currently only supports AES encryption.  However, many low-end
      mobile devices have older CPUs that don't have AES instructions, e.g.
      the ARMv8 Cryptography Extensions.  Currently, user data on such devices
      is not encrypted at rest because AES is too slow, even when the NEON
      bit-sliced implementation of AES is used.  Unfortunately, it is
      infeasible to encrypt these devices at all when AES is the only option.
      
      Therefore, this patch updates fscrypt to support the Speck block cipher,
      which was recently added to the crypto API.  The C implementation of
      Speck is not especially fast, but Speck can be implemented very
      efficiently with general-purpose vector instructions, e.g. ARM NEON.
      For example, on an ARMv7 processor, we measured the NEON-accelerated
      Speck128/256-XTS at 69 MB/s for both encryption and decryption, while
      AES-256-XTS with the NEON bit-sliced implementation was only 22 MB/s
      encryption and 19 MB/s decryption.
      
      There are multiple variants of Speck.  This patch only adds support for
      Speck128/256, which is the variant with a 128-bit block size and 256-bit
      key size -- the same as AES-256.  This is believed to be the most secure
      variant of Speck, and it's only about 6% slower than Speck128/128.
      Speck64/128 would be at least 20% faster because it has 20% rounds, and
      it can be even faster on CPUs that can't efficiently do the 64-bit
      operations needed for Speck128.  However, Speck64's 64-bit block size is
      not preferred security-wise.  ARM NEON also supports the needed 64-bit
      operations even on 32-bit CPUs, resulting in Speck128 being fast enough
      for our targeted use cases so far.
      
      The chosen modes of operation are XTS for contents and CTS-CBC for
      filenames.  These are the same modes of operation that fscrypt defaults
      to for AES.  Note that as with the other fscrypt modes, Speck will not
      be used unless userspace chooses to use it.  Nor are any of the existing
      modes (which are all AES-based) being removed, of course.
      
      We intentionally don't make CONFIG_FS_ENCRYPTION select
      CONFIG_CRYPTO_SPECK, so people will have to enable Speck support
      themselves if they need it.  This is because we shouldn't bloat the
      FS_ENCRYPTION dependencies with every new cipher, especially ones that
      aren't recommended for most users.  Moreover, CRYPTO_SPECK is just the
      generic implementation, which won't be fast enough for many users; in
      practice, they'll need to enable CRYPTO_SPECK_NEON to get acceptable
      performance.
      
      More details about our choice of Speck can be found in our patches that
      added Speck to the crypto API, and the follow-on discussion threads.
      We're planning a publication that explains the choice in more detail.
      But briefly, we can't use ChaCha20 as we previously proposed, since it
      would be insecure to use a stream cipher in this context, with potential
      IV reuse during writes on f2fs and/or on wear-leveling flash storage.
      
      We also evaluated many other lightweight and/or ARX-based block ciphers
      such as Chaskey-LTS, RC5, LEA, CHAM, Threefish, RC6, NOEKEON, SPARX, and
      XTEA.  However, all had disadvantages vs. Speck, such as insufficient
      performance with NEON, much less published cryptanalysis, or an
      insufficient security level.  Various design choices in Speck make it
      perform better with NEON than competing ciphers while still having a
      security margin similar to AES, and in the case of Speck128 also the
      same available security levels.  Unfortunately, Speck does have some
      political baggage attached -- it's an NSA designed cipher, and was
      rejected from an ISO standard (though for context, as far as I know none
      of the above-mentioned alternatives are ISO standards either).
      Nevertheless, we believe it is a good solution to the problem from a
      technical perspective.
      
      Certain algorithms constructed from ChaCha or the ChaCha permutation,
      such as MEM (Masked Even-Mansour) or HPolyC, may also meet our
      performance requirements.  However, these are new constructions that
      need more time to receive the cryptographic review and acceptance needed
      to be confident in their security.  HPolyC hasn't been published yet,
      and we are concerned that MEM makes stronger assumptions about the
      underlying permutation than the ChaCha stream cipher does.  In contrast,
      the XTS mode of operation is relatively well accepted, and Speck has
      over 70 cryptanalysis papers.  Of course, these ChaCha-based algorithms
      can still be added later if they become ready.
      
      The best known attack on Speck128/256 is a differential cryptanalysis
      attack on 25 of 34 rounds with 2^253 time complexity and 2^125 chosen
      plaintexts, i.e. only marginally faster than brute force.  There is no
      known attack on the full 34 rounds.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      12d28f79
    • E
      fscrypt: only derive the needed portion of the key · 646b7d4f
      Eric Biggers 提交于
      Currently the key derivation function in fscrypt uses the master key
      length as the amount of output key material to derive.  This works, but
      it means we can waste time deriving more key material than is actually
      used, e.g. most commonly, deriving 64 bytes for directories which only
      take a 32-byte AES-256-CTS-CBC key.  It also forces us to validate that
      the master key length is a multiple of AES_BLOCK_SIZE, which wouldn't
      otherwise be necessary.
      
      Fix it to only derive the needed length key.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      646b7d4f
    • E
      fscrypt: separate key lookup from key derivation · 590f497d
      Eric Biggers 提交于
      Refactor the confusingly-named function 'validate_user_key()' into a new
      function 'find_and_derive_key()' which first finds the keyring key, then
      does the key derivation.  Among other benefits this avoids the strange
      behavior we had previously where if key derivation failed for some
      reason, then we would fall back to the alternate key prefix.  Now, we'll
      only fall back to the alternate key prefix if a valid key isn't found.
      
      This patch also improves the warning messages that are logged when the
      keyring key's payload is invalid.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      590f497d
    • E
      fscrypt: use a common logging function · 544d08fd
      Eric Biggers 提交于
      Use a common function for fscrypt warning and error messages so that all
      the messages are consistently ratelimited, include the "fscrypt:"
      prefix, and include the filesystem name if applicable.
      
      Also fix up a few of the log messages to be more descriptive.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      544d08fd
    • E
      fscrypt: remove internal key size constants · 11b8818e
      Eric Biggers 提交于
      With one exception, the internal key size constants such as
      FS_AES_256_XTS_KEY_SIZE are only used for the 'available_modes' array,
      where they really only serve to obfuscate what the values are.  Also
      some of the constants are unused, and the key sizes tend to be in the
      names of the algorithms anyway.  In the past these values were also
      misused, e.g. we used to have FS_AES_256_XTS_KEY_SIZE in places that
      technically should have been FS_MAX_KEY_SIZE.
      
      The exception is that FS_AES_128_ECB_KEY_SIZE is used for key
      derivation.  But it's more appropriate to use
      FS_KEY_DERIVATION_NONCE_SIZE for that instead.
      
      Thus, just put the sizes directly in the 'available_modes' array.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      11b8818e
    • E
      fscrypt: remove unnecessary check for non-logon key type · 1086c80c
      Eric Biggers 提交于
      We're passing 'key_type_logon' to request_key(), so the found key is
      guaranteed to be of type "logon".  Thus, there is no reason to check
      later that the key is really a "logon" key.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      1086c80c
    • E
      fscrypt: don't clear flags on crypto transform · 101c97a3
      Eric Biggers 提交于
      fscrypt is clearing the flags on the crypto_skcipher it allocates for
      each inode.  But, this is unnecessary and may cause problems in the
      future because it will even clear flags that are meant to be internal to
      the crypto API, e.g. CRYPTO_TFM_NEED_KEY.
      
      Remove the unnecessary flag clearing.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      101c97a3
    • E
      fscrypt: remove unnecessary NULL check when allocating skcipher · 9919479b
      Eric Biggers 提交于
      crypto_alloc_skcipher() returns an ERR_PTR() on failure, not NULL.
      Remove the unnecessary check for NULL.
      Signed-off-by: NEric Biggers <ebiggers@google.com>
      Signed-off-by: NTheodore Ts'o <tytso@mit.edu>
      9919479b
  14. 12 1月, 2018 2 次提交
  15. 03 11月, 2017 1 次提交