KEYS: asym_tpm: Implement the decrypt operation [ver #2]
authorDenis Kenzior <denkenz@gmail.com>
Tue, 9 Oct 2018 16:49:13 +0000 (17:49 +0100)
committerJames Morris <james.morris@microsoft.com>
Fri, 26 Oct 2018 08:30:47 +0000 (09:30 +0100)
This patch implements the pkey_decrypt operation using the private key
blob.  The blob is first loaded into the TPM via tpm_loadkey2.  Once the
handle is obtained, tpm_unbind operation is used to decrypt the data on
the TPM and the result is returned.  The key loaded by tpm_loadkey2 is
then evicted via tpm_flushspecific operation.

This patch assumes that the SRK authorization is a well known 20-byte of
zeros and the same holds for the key authorization of the provided key.

Signed-off-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Marcel Holtmann <marcel@holtmann.org>
Reviewed-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: James Morris <james.morris@microsoft.com>
crypto/asymmetric_keys/asym_tpm.c

index e893b521222269abb9f34b01b935c07eaa896bc1..6f5d5cf98910d31d3a44a842a5524fca3e054e18 100644 (file)
@@ -341,7 +341,8 @@ static int tpm_key_query(const struct kernel_pkey_params *params,
        info->max_enc_size = len;
        info->max_dec_size = tk->key_len / 8;
 
-       info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
+       info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT |
+                             KEYCTL_SUPPORTS_DECRYPT;
 
        ret = 0;
 error_free_tfm:
@@ -410,6 +411,58 @@ error_free_tfm:
        return ret;
 }
 
+/*
+ * Decryption operation is performed with the private key in the TPM.
+ */
+static int tpm_key_decrypt(struct tpm_key *tk,
+                          struct kernel_pkey_params *params,
+                          const void *in, void *out)
+{
+       struct tpm_buf *tb;
+       uint32_t keyhandle;
+       uint8_t srkauth[SHA1_DIGEST_SIZE];
+       uint8_t keyauth[SHA1_DIGEST_SIZE];
+       int r;
+
+       pr_devel("==>%s()\n", __func__);
+
+       if (params->hash_algo)
+               return -ENOPKG;
+
+       if (strcmp(params->encoding, "pkcs1"))
+               return -ENOPKG;
+
+       tb = kzalloc(sizeof(*tb), GFP_KERNEL);
+       if (!tb)
+               return -ENOMEM;
+
+       /* TODO: Handle a non-all zero SRK authorization */
+       memset(srkauth, 0, sizeof(srkauth));
+
+       r = tpm_loadkey2(tb, SRKHANDLE, srkauth,
+                               tk->blob, tk->blob_len, &keyhandle);
+       if (r < 0) {
+               pr_devel("loadkey2 failed (%d)\n", r);
+               goto error;
+       }
+
+       /* TODO: Handle a non-all zero key authorization */
+       memset(keyauth, 0, sizeof(keyauth));
+
+       r = tpm_unbind(tb, keyhandle, keyauth,
+                      in, params->in_len, out, params->out_len);
+       if (r < 0)
+               pr_devel("tpm_unbind failed (%d)\n", r);
+
+       if (tpm_flushspecific(tb, keyhandle) < 0)
+               pr_devel("flushspecific failed (%d)\n", r);
+
+error:
+       kzfree(tb);
+       pr_devel("<==%s() = %d\n", __func__, r);
+       return r;
+}
+
 /*
  * Do encryption, decryption and signing ops.
  */
@@ -424,6 +477,9 @@ static int tpm_key_eds_op(struct kernel_pkey_params *params,
        case kernel_pkey_encrypt:
                ret = tpm_key_encrypt(tk, params, in, out);
                break;
+       case kernel_pkey_decrypt:
+               ret = tpm_key_decrypt(tk, params, in, out);
+               break;
        default:
                BUG();
        }