Merge tag 'libnvdimm-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdim...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Dec 2018 23:05:13 +0000 (15:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 28 Dec 2018 23:05:13 +0000 (15:05 -0800)
Pull libnvdimm updates from Dan Williams:
 "The vast bulk of this update is the new support for the security
  capabilities of some nvdimms.

  The userspace tooling for this capability is still a work in progress,
  but the changes survive the existing libnvdimm unit tests. The changes
  also pass manual checkout on hardware and the new nfit_test emulation
  of the security capability.

  The touches of the security/keys/ files have received the necessary
  acks from Mimi and David. Those changes were necessary to allow for a
  new generic encrypted-key type, and allow the nvdimm sub-system to
  lookup key material referenced by the libnvdimm-sysfs interface.

  Summary:

   - Add support for the security features of nvdimm devices that
     implement a security model similar to ATA hard drive security. The
     security model supports locking access to the media at
     device-power-loss, to be unlocked with a passphrase, and
     secure-erase (crypto-scramble).

     Unlike the ATA security case where the kernel expects device
     security to be managed in a pre-OS environment, the libnvdimm
     security implementation allows key provisioning and key-operations
     at OS runtime. Keys are managed with the kernel's encrypted-keys
     facility to provide data-at-rest security for the libnvdimm key
     material. The usage model mirrors fscrypt key management, but is
     driven via libnvdimm sysfs.

   - Miscellaneous updates for api usage and comment fixes"

* tag 'libnvdimm-for-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: (21 commits)
  libnvdimm/security: Quiet security operations
  libnvdimm/security: Add documentation for nvdimm security support
  tools/testing/nvdimm: add Intel DSM 1.8 support for nfit_test
  tools/testing/nvdimm: Add overwrite support for nfit_test
  tools/testing/nvdimm: Add test support for Intel nvdimm security DSMs
  acpi/nfit, libnvdimm/security: add Intel DSM 1.8 master passphrase support
  acpi/nfit, libnvdimm/security: Add security DSM overwrite support
  acpi/nfit, libnvdimm: Add support for issue secure erase DSM to Intel nvdimm
  acpi/nfit, libnvdimm: Add enable/update passphrase support for Intel nvdimms
  acpi/nfit, libnvdimm: Add disable passphrase support to Intel nvdimm.
  acpi/nfit, libnvdimm: Add unlock of nvdimm support for Intel DIMMs
  acpi/nfit, libnvdimm: Add freeze security support to Intel nvdimm
  acpi/nfit, libnvdimm: Introduce nvdimm_security_ops
  keys-encrypted: add nvdimm key format type to encrypted keys
  keys: Export lookup_user_key to external users
  acpi/nfit, libnvdimm: Store dimm id as a member to struct nvdimm
  libnvdimm, namespace: Replace kmemdup() with kstrndup()
  libnvdimm, label: Switch to bitmap_zalloc()
  ACPI/nfit: Adjust annotation for why return 0 if fail to find NFIT at start
  libnvdimm, bus: Check id immediately following ida_simple_get
  ...

1  2 
security/keys/encrypted-keys/encrypted.c
security/keys/process_keys.c

@@@ -45,6 -45,7 +45,7 @@@ static const char hmac_alg[] = "hmac(sh
  static const char blkcipher_alg[] = "cbc(aes)";
  static const char key_format_default[] = "default";
  static const char key_format_ecryptfs[] = "ecryptfs";
+ static const char key_format_enc32[] = "enc32";
  static unsigned int ivsize;
  static int blksize;
  
@@@ -54,6 -55,7 +55,7 @@@
  #define HASH_SIZE SHA256_DIGEST_SIZE
  #define MAX_DATA_SIZE 4096
  #define MIN_DATA_SIZE  20
+ #define KEY_ENC32_PAYLOAD_LEN 32
  
  static struct crypto_shash *hash_tfm;
  
@@@ -62,12 -64,13 +64,13 @@@ enum 
  };
  
  enum {
-       Opt_error = -1, Opt_default, Opt_ecryptfs
+       Opt_error = -1, Opt_default, Opt_ecryptfs, Opt_enc32
  };
  
  static const match_table_t key_format_tokens = {
        {Opt_default, "default"},
        {Opt_ecryptfs, "ecryptfs"},
+       {Opt_enc32, "enc32"},
        {Opt_error, NULL}
  };
  
@@@ -195,6 -198,7 +198,7 @@@ static int datablob_parse(char *datablo
        key_format = match_token(p, key_format_tokens, args);
        switch (key_format) {
        case Opt_ecryptfs:
+       case Opt_enc32:
        case Opt_default:
                *format = p;
                *master_desc = strsep(&datablob, " \t");
@@@ -342,7 -346,7 +346,7 @@@ static int calc_hmac(u8 *digest, const 
        struct crypto_shash *tfm;
        int err;
  
 -      tfm = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC);
 +      tfm = crypto_alloc_shash(hmac_alg, 0, 0);
        if (IS_ERR(tfm)) {
                pr_err("encrypted_key: can't alloc %s transform: %ld\n",
                       hmac_alg, PTR_ERR(tfm));
@@@ -625,15 -629,22 +629,22 @@@ static struct encrypted_key_payload *en
        format_len = (!format) ? strlen(key_format_default) : strlen(format);
        decrypted_datalen = dlen;
        payload_datalen = decrypted_datalen;
-       if (format && !strcmp(format, key_format_ecryptfs)) {
-               if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
-                       pr_err("encrypted_key: keylen for the ecryptfs format "
-                              "must be equal to %d bytes\n",
-                              ECRYPTFS_MAX_KEY_BYTES);
-                       return ERR_PTR(-EINVAL);
+       if (format) {
+               if (!strcmp(format, key_format_ecryptfs)) {
+                       if (dlen != ECRYPTFS_MAX_KEY_BYTES) {
+                               pr_err("encrypted_key: keylen for the ecryptfs format must be equal to %d bytes\n",
+                                       ECRYPTFS_MAX_KEY_BYTES);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES;
+                       payload_datalen = sizeof(struct ecryptfs_auth_tok);
+               } else if (!strcmp(format, key_format_enc32)) {
+                       if (decrypted_datalen != KEY_ENC32_PAYLOAD_LEN) {
+                               pr_err("encrypted_key: enc32 key payload incorrect length: %d\n",
+                                               decrypted_datalen);
+                               return ERR_PTR(-EINVAL);
+                       }
                }
-               decrypted_datalen = ECRYPTFS_MAX_KEY_BYTES;
-               payload_datalen = sizeof(struct ecryptfs_auth_tok);
        }
  
        encrypted_datalen = roundup(decrypted_datalen, blksize);
@@@ -984,7 -995,7 +995,7 @@@ static int __init init_encrypted(void
  {
        int ret;
  
 -      hash_tfm = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC);
 +      hash_tfm = crypto_alloc_shash(hash_alg, 0, 0);
        if (IS_ERR(hash_tfm)) {
                pr_err("encrypted_key: can't allocate %s transform: %ld\n",
                       hash_alg, PTR_ERR(hash_tfm));
@@@ -9,6 -9,7 +9,6 @@@
   * 2 of the License, or (at your option) any later version.
   */
  
 -#include <linux/module.h>
  #include <linux/init.h>
  #include <linux/sched.h>
  #include <linux/sched/user.h>
@@@ -754,6 -755,7 +754,7 @@@ reget_creds
        put_cred(ctx.cred);
        goto try_again;
  }
+ EXPORT_SYMBOL(lookup_user_key);
  
  /*
   * Join the named keyring as the session keyring if possible else attempt to