From: Alison Schofield <alison.schofi...@intel.com>

In preparation for programming the key into the hardware, move
the key payload into a cache aligned structure. This alignment
is a requirement of the MKTME hardware.

Use the slab allocator to have this structure readily available.

Signed-off-by: Alison Schofield <alison.schofi...@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shute...@linux.intel.com>
---
 security/keys/mktme_keys.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/security/keys/mktme_keys.c b/security/keys/mktme_keys.c
index 10fcdbf5a08f..8ac75b1e6188 100644
--- a/security/keys/mktme_keys.c
+++ b/security/keys/mktme_keys.c
@@ -16,6 +16,7 @@
 
 static DEFINE_SPINLOCK(mktme_lock);
 static unsigned int mktme_available_keyids;  /* Free Hardware KeyIDs */
+static struct kmem_cache *mktme_prog_cache;  /* Hardware programming cache */
 
 enum mktme_keyid_state {
        KEYID_AVAILABLE,        /* Available to be assigned */
@@ -79,6 +80,25 @@ static const match_table_t mktme_token = {
        {OPT_ERROR, NULL}
 };
 
+/* Copy the payload to the HW programming structure and program this KeyID */
+static int mktme_program_keyid(int keyid, u32 payload)
+{
+       struct mktme_key_program *kprog = NULL;
+       int ret;
+
+       kprog = kmem_cache_zalloc(mktme_prog_cache, GFP_KERNEL);
+       if (!kprog)
+               return -ENOMEM;
+
+       /* Hardware programming requires cached aligned struct */
+       kprog->keyid = keyid;
+       kprog->keyid_ctrl = payload;
+
+       ret = MKTME_PROG_SUCCESS;       /* Future programming call */
+       kmem_cache_free(mktme_prog_cache, kprog);
+       return ret;
+}
+
 /* Key Service Method called when a Userspace Key is garbage collected. */
 static void mktme_destroy_key(struct key *key)
 {
@@ -93,6 +113,7 @@ static void mktme_destroy_key(struct key *key)
 /* Key Service Method to create a new key. Payload is preparsed. */
 int mktme_instantiate_key(struct key *key, struct key_preparsed_payload *prep)
 {
+       u32 *payload = prep->payload.data[0];
        unsigned long flags;
        int keyid;
 
@@ -101,7 +122,14 @@ int mktme_instantiate_key(struct key *key, struct 
key_preparsed_payload *prep)
        spin_unlock_irqrestore(&mktme_lock, flags);
        if (!keyid)
                return -ENOKEY;
-       return 0;
+
+       if (!mktme_program_keyid(keyid, *payload))
+               return MKTME_PROG_SUCCESS;
+
+       spin_lock_irqsave(&mktme_lock, flags);
+       mktme_release_keyid(keyid);
+       spin_unlock_irqrestore(&mktme_lock, flags);
+       return -ENOKEY;
 }
 
 /* Make sure arguments are correct for the TYPE of key requested */
@@ -245,10 +273,15 @@ static int __init init_mktme(void)
        if (!mktme_map)
                return -ENOMEM;
 
+       /* Used to program the hardware key tables */
+       mktme_prog_cache = KMEM_CACHE(mktme_key_program, SLAB_PANIC);
+       if (!mktme_prog_cache)
+               goto free_map;
+
        ret = register_key_type(&key_type_mktme);
        if (!ret)
                return ret;                     /* SUCCESS */
-
+free_map:
        kvfree(mktme_map);
 
        return -ENOMEM;
-- 
2.21.0

Reply via email to