tpm2-util: add common parser for the LUKS2 TPM2 JSON structure
authorLennart Poettering <lennart@poettering.net>
Fri, 19 Aug 2022 20:15:12 +0000 (22:15 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 8 Sep 2022 14:34:27 +0000 (16:34 +0200)
This splits out the JSON parser used by the systemd-cryptsetup code.

This is preparation for later work to reuse it in the tpm2 cryptsetup
token module, which currently uses a separate but very similar parser
for the same data.

No change in behaviour.

src/cryptsetup/cryptsetup-tpm2.c
src/cryptsetup/cryptsetup-tpm2.h
src/cryptsetup/cryptsetup.c
src/shared/cryptsetup-util.c
src/shared/cryptsetup-util.h
src/shared/tpm2-util.c
src/shared/tpm2-util.h

index 7469e7da1bf6b1bc439b19a268e7daecbe82d576..838c02bfc96d62f3032fdd76226fd23c55c6b8b5 100644 (file)
@@ -188,24 +188,22 @@ int find_tpm2_auto_data(
                 size_t *ret_blob_size,
                 void **ret_policy_hash,
                 size_t *ret_policy_hash_size,
+                TPM2Flags *ret_flags,
                 int *ret_keyslot,
-                int *ret_token,
-                TPM2Flags *ret_flags) {
+                int *ret_token) {
 
-        _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL;
-        size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0;
-        int r, keyslot = -1, token = -1;
-        TPM2Flags flags = 0;
-        uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
-        uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
-        uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
+        int r, token;
 
         assert(cd);
 
         for (token = start_token; token < sym_crypt_token_max(CRYPT_LUKS2); token++) {
+                _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL;
                 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
-                JsonVariant *w;
-                int ks;
+                size_t blob_size, policy_hash_size, pubkey_size;
+                uint32_t hash_pcr_mask, pubkey_pcr_mask;
+                uint16_t pcr_bank, primary_alg;
+                TPM2Flags flags;
+                int keyslot;
 
                 r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v);
                 if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE))
@@ -213,137 +211,46 @@ int find_tpm2_auto_data(
                 if (r < 0)
                         return log_error_errno(r, "Failed to read JSON token data off disk: %m");
 
-                ks = cryptsetup_get_keyslot_from_token(v);
-                if (ks < 0) {
-                        /* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by
-                         * us, but by the LUKS2 spec */
-                        log_warning_errno(ks, "Failed to extract keyslot index from TPM2 JSON data token %i, skipping: %m", token);
+                r = tpm2_parse_luks2_json(
+                                v,
+                                &keyslot,
+                                &hash_pcr_mask,
+                                &pcr_bank,
+                                &pubkey, &pubkey_size,
+                                &pubkey_pcr_mask,
+                                &primary_alg,
+                                &blob, &blob_size,
+                                &policy_hash, &policy_hash_size,
+                                &flags);
+                if (r == -EUCLEAN) /* Gracefully handle issues in JSON fields not owned by us */
                         continue;
-                }
-
-                w = json_variant_by_key(v, "tpm2-pcrs");
-                if (!w)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "TPM2 token data lacks 'tpm2-pcrs' field.");
-
-                r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to parse TPM2 PCR mask: %m");
-
-                if (search_pcr_mask != UINT32_MAX &&
-                    search_pcr_mask != hash_pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */
-                        continue;
-
-                assert(keyslot < 0);
-                keyslot = ks;
-
-                assert(pcr_bank == UINT16_MAX);
-                assert(primary_alg == TPM2_ALG_ECC);
-
-                /* The bank field is optional, since it was added in systemd 250 only. Before the bank was
-                 * hardcoded to SHA256. */
-                w = json_variant_by_key(v, "tpm2-pcr-bank");
-                if (w) {
-                        /* The PCR bank field is optional */
-
-                        if (!json_variant_is_string(w))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "TPM2 PCR bank is not a string.");
-
-                        r = tpm2_pcr_bank_from_string(json_variant_string(w));
-                        if (r < 0)
-                                return log_error_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
-
-                        pcr_bank = r;
-                }
-
-                /* The primary key algorithm field is optional, since it was also added in systemd 250
-                 * only. Before the algorithm was hardcoded to ECC. */
-                w = json_variant_by_key(v, "tpm2-primary-alg");
-                if (w) {
-                        /* The primary key algorithm is optional */
-
-                        if (!json_variant_is_string(w))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "TPM2 primary key algorithm is not a string.");
-
-                        r = tpm2_primary_alg_from_string(json_variant_string(w));
-                        if (r < 0)
-                                return log_error_errno(r, "TPM2 primary key algorithm invalid or not supported: %s", json_variant_string(w));
-
-                        primary_alg = r;
-                }
-
-                assert(!blob);
-                w = json_variant_by_key(v, "tpm2-blob");
-                if (!w || !json_variant_is_string(w))
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "TPM2 token data lacks 'tpm2-blob' field.");
-
-                r = unbase64mem(json_variant_string(w), SIZE_MAX, &blob, &blob_size);
-                if (r < 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Invalid base64 data in 'tpm2-blob' field.");
-
-                assert(!policy_hash);
-                w = json_variant_by_key(v, "tpm2-policy-hash");
-                if (!w || !json_variant_is_string(w))
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "TPM2 token data lacks 'tpm2-policy-hash' field.");
-
-                r = unhexmem(json_variant_string(w), SIZE_MAX, &policy_hash, &policy_hash_size);
                 if (r < 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                               "Invalid base64 data in 'tpm2-policy-hash' field.");
-
-                w = json_variant_by_key(v, "tpm2-pin");
-                if (w) {
-                        if (!json_variant_is_boolean(w))
-                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
-                                                       "TPM2 PIN policy is not a boolean.");
-
-                        if (json_variant_boolean(w))
-                                flags |= TPM2_FLAGS_USE_PIN;
+                        return log_error_errno(r, "Failed to parse TPM2 JSON data: %m");
+
+                if (search_pcr_mask == UINT32_MAX ||
+                    search_pcr_mask == hash_pcr_mask) {
+
+                        if (start_token <= 0)
+                                log_info("Automatically discovered security TPM2 token unlocks volume.");
+
+                        *ret_hash_pcr_mask = hash_pcr_mask;
+                        *ret_pcr_bank = pcr_bank;
+                        *ret_pubkey = TAKE_PTR(pubkey);
+                        *ret_pubkey_size = pubkey_size;
+                        *ret_pubkey_pcr_mask = pubkey_pcr_mask;
+                        *ret_primary_alg = primary_alg;
+                        *ret_blob = TAKE_PTR(blob);
+                        *ret_blob_size = blob_size;
+                        *ret_policy_hash = TAKE_PTR(policy_hash);
+                        *ret_policy_hash_size = policy_hash_size;
+                        *ret_keyslot = keyslot;
+                        *ret_token = token;
+                        *ret_flags = flags;
+                        return 0;
                 }
 
-                w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
-                if (w) {
-                        r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
-                        if (r < 0)
-                                return r;
-                }
-
-                w = json_variant_by_key(v, "tpm2_pubkey");
-                if (w) {
-                        r = json_variant_unbase64(w, &pubkey, &pubkey_size);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to decode PCR public key.");
-                } else if (pubkey_pcr_mask != 0)
-                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
-
-                break;
+                /* PCR mask doesn't match what is configured, ignore this entry, let's see next */
         }
 
-        if (!blob)
-                return log_error_errno(SYNTHETIC_ERRNO(ENXIO),
-                                       "No valid TPM2 token data found.");
-
-        if (start_token <= 0)
-                log_info("Automatically discovered security TPM2 token unlocks volume.");
-
-        *ret_hash_pcr_mask = hash_pcr_mask;
-        *ret_pcr_bank = pcr_bank;
-        *ret_pubkey = TAKE_PTR(pubkey);
-        *ret_pubkey_size = pubkey_size;
-        *ret_pubkey_pcr_mask = pubkey_pcr_mask;
-        *ret_primary_alg = primary_alg;
-        *ret_blob = TAKE_PTR(blob);
-        *ret_blob_size = blob_size;
-        *ret_policy_hash = TAKE_PTR(policy_hash);
-        *ret_policy_hash_size = policy_hash_size;
-        *ret_keyslot = keyslot;
-        *ret_token = token;
-        *ret_flags = flags;
-
-        return 0;
+        return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "No valid TPM2 token data found.");
 }
index b1bcf6de1062483b0363b1abfd858257185b1b9d..a34eb8443d4352842e8b8f42a6e50d761018e865 100644 (file)
@@ -49,9 +49,9 @@ int find_tpm2_auto_data(
                 size_t *ret_blob_size,
                 void **ret_policy_hash,
                 size_t *ret_policy_hash_size,
+                TPM2Flags *ret_flags,
                 int *ret_keyslot,
-                int *ret_token,
-                TPM2Flags *ret_flags);
+                int *ret_token);
 
 #else
 
@@ -97,9 +97,9 @@ static inline int find_tpm2_auto_data(
                 size_t *ret_blob_size,
                 void **ret_policy_hash,
                 size_t *ret_policy_hash_size,
+                TPM2Flags *ret_flags,
                 int *ret_keyslot,
-                int *ret_token,
-                TPM2Flags *ret_flags) {
+                int *ret_token) {
 
         return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
                                "TPM2 support not available.");
index c419354bf595abaa7ada9a16c6b474821bf7cf98..406369329c365c8c274cacccb9f53ba9c05278ca 100644 (file)
@@ -1522,9 +1522,9 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2(
                                                 &primary_alg,
                                                 &blob, &blob_size,
                                                 &policy_hash, &policy_hash_size,
+                                                &tpm2_flags,
                                                 &keyslot,
-                                                &token,
-                                                &tpm2_flags);
+                                                &token);
                                 if (r == -ENXIO)
                                         /* No further TPM2 tokens found in the LUKS2 header. */
                                         return log_full_errno(found_some ? LOG_NOTICE : LOG_DEBUG,
index b93f702aff994959d2c604b357d38ec2bc1d6a81..da6dcb2f093aa9681665f21cd720b1cd77f96ef7 100644 (file)
@@ -1,12 +1,12 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#if HAVE_LIBCRYPTSETUP
 #include "alloc-util.h"
 #include "cryptsetup-util.h"
 #include "dlfcn-util.h"
 #include "log.h"
 #include "parse-util.h"
 
+#if HAVE_LIBCRYPTSETUP
 static void *cryptsetup_dl = NULL;
 
 int (*sym_crypt_activate_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags);
@@ -224,6 +224,28 @@ int cryptsetup_get_token_as_json(
         return 0;
 }
 
+int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v) {
+        _cleanup_free_ char *text = NULL;
+        int r;
+
+        r = dlopen_cryptsetup();
+        if (r < 0)
+                return r;
+
+        r = json_variant_format(v, 0, &text);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to format token data for LUKS: %m");
+
+        log_debug("Adding token text <%s>", text);
+
+        r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to write token data to LUKS: %m");
+
+        return 0;
+}
+#endif
+
 int cryptsetup_get_keyslot_from_token(JsonVariant *v) {
         int keyslot, r;
         JsonVariant *w;
@@ -252,25 +274,3 @@ int cryptsetup_get_keyslot_from_token(JsonVariant *v) {
 
         return keyslot;
 }
-
-int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v) {
-        _cleanup_free_ char *text = NULL;
-        int r;
-
-        r = dlopen_cryptsetup();
-        if (r < 0)
-                return r;
-
-        r = json_variant_format(v, 0, &text);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to format token data for LUKS: %m");
-
-        log_debug("Adding token text <%s>", text);
-
-        r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
-        if (r < 0)
-                return log_debug_errno(r, "Failed to write token data to LUKS: %m");
-
-        return 0;
-}
-#endif
index 2a17820d63976decebd9a5de1a22d7aecbb08520..fc80edb4112a5084293e9448229b002d5d9b1594 100644 (file)
@@ -74,7 +74,6 @@ void cryptsetup_enable_logging(struct crypt_device *cd);
 int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd);
 
 int cryptsetup_get_token_as_json(struct crypt_device *cd, int idx, const char *verify_type, JsonVariant **ret);
-int cryptsetup_get_keyslot_from_token(JsonVariant *v);
 int cryptsetup_add_token_json(struct crypt_device *cd, JsonVariant *v);
 
 #else
@@ -87,6 +86,8 @@ static inline void sym_crypt_freep(struct crypt_device** cd) {}
 
 #endif
 
+int cryptsetup_get_keyslot_from_token(JsonVariant *v);
+
 static inline const char *mangle_none(const char *s) {
         /* A helper that turns cryptsetup/integritysetup/veritysetup "options" strings into NULL if they are effectively empty */
         return isempty(s) || STR_IN_SET(s, "-", "none") ? NULL : s;
index 254e63334a270f891c3f3390f7fa117bd8c684c8..f5b97fae73a70ab76e1bf85cfcdb4db72e11bca5 100644 (file)
@@ -1,17 +1,12 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include "efi-api.h"
-#include "extract-word.h"
-#include "parse-util.h"
-#include "stat-util.h"
-#include "tpm2-util.h"
-#include "virt.h"
-
-#if HAVE_TPM2
 #include "alloc-util.h"
+#include "cryptsetup-util.h"
 #include "def.h"
 #include "dirent-util.h"
 #include "dlfcn-util.h"
+#include "efi-api.h"
+#include "extract-word.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-table.h"
 #include "hexdecoct.h"
 #include "memory-util.h"
 #include "openssl-util.h"
+#include "parse-util.h"
 #include "random-util.h"
 #include "sha256.h"
+#include "stat-util.h"
 #include "time-util.h"
+#include "tpm2-util.h"
+#include "virt.h"
 
+#if HAVE_TPM2
 static void *libtss2_esys_dl = NULL;
 static void *libtss2_rc_dl = NULL;
 static void *libtss2_mu_dl = NULL;
@@ -1881,6 +1881,150 @@ int tpm2_make_luks2_json(
         return keyslot;
 }
 
+int tpm2_parse_luks2_json(
+                JsonVariant *v,
+                int *ret_keyslot,
+                uint32_t *ret_hash_pcr_mask,
+                uint16_t *ret_pcr_bank,
+                void **ret_pubkey,
+                size_t *ret_pubkey_size,
+                uint32_t *ret_pubkey_pcr_mask,
+                uint16_t *ret_primary_alg,
+                void **ret_blob,
+                size_t *ret_blob_size,
+                void **ret_policy_hash,
+                size_t *ret_policy_hash_size,
+                TPM2Flags *ret_flags) {
+
+        _cleanup_free_ void *blob = NULL, *policy_hash = NULL, *pubkey = NULL;
+        size_t blob_size = 0, policy_hash_size = 0, pubkey_size = 0;
+        uint32_t hash_pcr_mask = 0, pubkey_pcr_mask = 0;
+        uint16_t primary_alg = TPM2_ALG_ECC; /* ECC was the only supported algorithm in systemd < 250, use that as implied default, for compatibility */
+        uint16_t pcr_bank = UINT16_MAX; /* default: pick automatically */
+        int r, keyslot = -1;
+        TPM2Flags flags = 0;
+        JsonVariant *w;
+
+        assert(v);
+
+        if (ret_keyslot) {
+                keyslot = cryptsetup_get_keyslot_from_token(v);
+                if (keyslot < 0) {
+                        /* Return a recognizable error when parsing this field, so that callers can handle parsing
+                         * errors of the keyslots field gracefully, since it's not 'owned' by us, but by the LUKS2
+                         * spec */
+                        log_debug_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data token, skipping: %m");
+                        return -EUCLEAN;
+                }
+        }
+
+        w = json_variant_by_key(v, "tpm2-pcrs");
+        if (!w)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-pcrs' field.");
+
+        r = tpm2_parse_pcr_json_array(w, &hash_pcr_mask);
+        if (r < 0)
+                return log_debug_errno(r, "Failed to parse TPM2 PCR mask: %m");
+
+        /* The bank field is optional, since it was added in systemd 250 only. Before the bank was hardcoded
+         * to SHA256. */
+        w = json_variant_by_key(v, "tpm2-pcr-bank");
+        if (w) {
+                /* The PCR bank field is optional */
+
+                if (!json_variant_is_string(w))
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PCR bank is not a string.");
+
+                r = tpm2_pcr_bank_from_string(json_variant_string(w));
+                if (r < 0)
+                        return log_debug_errno(r, "TPM2 PCR bank invalid or not supported: %s", json_variant_string(w));
+
+                pcr_bank = r;
+        }
+
+        /* The primary key algorithm field is optional, since it was also added in systemd 250 only. Before
+         * the algorithm was hardcoded to ECC. */
+        w = json_variant_by_key(v, "tpm2-primary-alg");
+        if (w) {
+                /* The primary key algorithm is optional */
+
+                if (!json_variant_is_string(w))
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 primary key algorithm is not a string.");
+
+                r = tpm2_primary_alg_from_string(json_variant_string(w));
+                if (r < 0)
+                        return log_debug_errno(r, "TPM2 primary key algorithm invalid or not supported: %s", json_variant_string(w));
+
+                primary_alg = r;
+        }
+
+        w = json_variant_by_key(v, "tpm2-blob");
+        if (!w)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-blob' field.");
+
+        r = json_variant_unbase64(w, &blob, &blob_size);
+        if (r < 0)
+                return log_debug_errno(r, "Invalid base64 data in 'tpm2-blob' field.");
+
+        w = json_variant_by_key(v, "tpm2-policy-hash");
+        if (!w)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 token data lacks 'tpm2-policy-hash' field.");
+
+        r = json_variant_unhex(w, &policy_hash, &policy_hash_size);
+        if (r < 0)
+                return log_debug_errno(r, "Invalid base64 data in 'tpm2-policy-hash' field.");
+
+        w = json_variant_by_key(v, "tpm2-pin");
+        if (w) {
+                if (!json_variant_is_boolean(w))
+                        return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "TPM2 PIN policy is not a boolean.");
+
+                SET_FLAG(flags, TPM2_FLAGS_USE_PIN, json_variant_boolean(w));
+        }
+
+        w = json_variant_by_key(v, "tpm2_pubkey_pcrs");
+        if (w) {
+                r = tpm2_parse_pcr_json_array(w, &pubkey_pcr_mask);
+                if (r < 0)
+                        return r;
+        }
+
+        w = json_variant_by_key(v, "tpm2_pubkey");
+        if (w) {
+                r = json_variant_unbase64(w, &pubkey, &pubkey_size);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to decode PCR public key.");
+        } else if (pubkey_pcr_mask != 0)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Public key PCR mask set, but not public key included in JSON data, refusing.");
+
+        if (ret_keyslot)
+                *ret_keyslot = keyslot;
+        if (ret_hash_pcr_mask)
+                *ret_hash_pcr_mask = hash_pcr_mask;
+        if (ret_pcr_bank)
+                *ret_pcr_bank = pcr_bank;
+        if (ret_pubkey)
+                *ret_pubkey = TAKE_PTR(pubkey);
+        if (ret_pubkey_size)
+                *ret_pubkey_size = pubkey_size;
+        if (ret_pubkey_pcr_mask)
+                *ret_pubkey_pcr_mask = pubkey_pcr_mask;
+        if (ret_primary_alg)
+                *ret_primary_alg = primary_alg;
+        if (ret_blob)
+                *ret_blob = TAKE_PTR(blob);
+        if (ret_blob_size)
+                *ret_blob_size = blob_size;
+        if (ret_policy_hash)
+                *ret_policy_hash = TAKE_PTR(policy_hash);
+        if (ret_policy_hash_size)
+                *ret_policy_hash_size = policy_hash_size;
+        if (ret_flags)
+                *ret_flags = flags;
+
+        return 0;
+}
+
 const char *tpm2_pcr_bank_to_string(uint16_t bank) {
         if (bank == TPM2_ALG_SHA1)
                 return "sha1";
index 3bdeba8f11c50a2e36b97e3fb24e430cd2850b58..2ff7c0eb63b01a0a15104326360693f23d872cda 100644 (file)
@@ -82,6 +82,7 @@ int tpm2_make_pcr_json_array(uint32_t pcr_mask, JsonVariant **ret);
 int tpm2_parse_pcr_json_array(JsonVariant *v, uint32_t *ret);
 
 int tpm2_make_luks2_json(int keyslot, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, TPM2Flags flags, JsonVariant **ret);
+int tpm2_parse_luks2_json(JsonVariant *v, int *ret_keyslot, uint32_t *ret_hash_pcr_mask, uint16_t *ret_pcr_bank, void **ret_pubkey, size_t *ret_pubkey_size, uint32_t *ret_pubkey_pcr_mask, uint16_t *ret_primary_alg, void **ret_blob, size_t *ret_blob_size, void **ret_policy_hash, size_t *ret_policy_hash_size, TPM2Flags *ret_flags);
 
 #define TPM2_PCRS_MAX 24U