Merge branch 'smack-for-4.5' of https://github.com/cschaufler/smack-next into next
[cascardo/linux.git] / drivers / char / tpm / tpm2-cmd.c
index c121304..45a6340 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "tpm.h"
+#include <crypto/hash_info.h>
 #include <keys/trusted-type.h>
 
 enum tpm2_object_attributes {
@@ -104,6 +105,19 @@ struct tpm2_cmd {
        union tpm2_cmd_params   params;
 } __packed;
 
+struct tpm2_hash {
+       unsigned int crypto_id;
+       unsigned int tpm_id;
+};
+
+static struct tpm2_hash tpm2_hash_map[] = {
+       {HASH_ALGO_SHA1, TPM2_ALG_SHA1},
+       {HASH_ALGO_SHA256, TPM2_ALG_SHA256},
+       {HASH_ALGO_SHA384, TPM2_ALG_SHA384},
+       {HASH_ALGO_SHA512, TPM2_ALG_SHA512},
+       {HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
+};
+
 /*
  * Array with one entry per ordinal defining the maximum amount
  * of time the chip could take to return the result. The values
@@ -429,8 +443,20 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 {
        unsigned int blob_len;
        struct tpm_buf buf;
+       u32 hash;
+       int i;
        int rc;
 
+       for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
+               if (options->hash == tpm2_hash_map[i].crypto_id) {
+                       hash = tpm2_hash_map[i].tpm_id;
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(tpm2_hash_map))
+               return -EINVAL;
+
        rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
        if (rc)
                return rc;
@@ -452,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
        tpm_buf_append_u8(&buf, payload->migratable);
 
        /* public */
-       tpm_buf_append_u16(&buf, 14);
+       if (options->policydigest)
+               tpm_buf_append_u16(&buf, 14 + options->digest_len);
+       else
+               tpm_buf_append_u16(&buf, 14);
 
        tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
-       tpm_buf_append_u16(&buf, TPM2_ALG_SHA256);
-       tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
-       tpm_buf_append_u16(&buf, 0); /* policy digest size */
+       tpm_buf_append_u16(&buf, hash);
+
+       /* policy */
+       if (options->policydigest) {
+               tpm_buf_append_u32(&buf, 0);
+               tpm_buf_append_u16(&buf, options->digest_len);
+               tpm_buf_append(&buf, options->policydigest,
+                              options->digest_len);
+       } else {
+               tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+               tpm_buf_append_u16(&buf, 0);
+       }
+
+       /* public parameters */
        tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
        tpm_buf_append_u16(&buf, 0);
 
@@ -488,8 +528,12 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 out:
        tpm_buf_destroy(&buf);
 
-       if (rc > 0)
-               rc = -EPERM;
+       if (rc > 0) {
+               if ((rc & TPM2_RC_HASH) == TPM2_RC_HASH)
+                       rc = -EINVAL;
+               else
+                       rc = -EPERM;
+       }
 
        return rc;
 }
@@ -583,7 +627,9 @@ static int tpm2_unseal(struct tpm_chip *chip,
                return rc;
 
        tpm_buf_append_u32(&buf, blob_handle);
-       tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+       tpm2_buf_append_auth(&buf,
+                            options->policyhandle ?
+                            options->policyhandle : TPM2_RS_PW,
                             NULL /* nonce */, 0,
                             0 /* session_attributes */,
                             options->blobauth /* hmac */,