For the moment only the system-tpm2 token type is supported.
Signed-off-by: Yann Diorcet <[email protected]>
---
grub-core/disk/luks2.c | 152 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 149 insertions(+), 3 deletions(-)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 8036d76ff..abe751d64 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -36,6 +36,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define LUKS_MAGIC_1ST "LUKS\xBA\xBE"
#define LUKS_MAGIC_2ND "SKUL\xBA\xBE"
+/* From tss2_types.h */
+#define TPM_MAX_PCRS 24
+
enum grub_luks2_kdf_type
{
LUKS2_KDF_TYPE_ARGON2I,
@@ -125,6 +128,51 @@ struct grub_luks2_digest
};
typedef struct grub_luks2_digest grub_luks2_digest_t;
+
+enum grub_luks2_token_type
+{
+ LUKS2_TOKEN_TYPE_NONE,
+ LUKS2_TOKEN_TYPE_SYSTEMD_TPM2
+};
+
+typedef enum grub_luks2_token_type grub_luks2_token_type_t;
+
+enum grub_luks2_token_systemd_tpm2_algo_type
+{
+ LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC,
+ LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_RSA
+};
+
+typedef enum grub_luks2_token_systemd_tpm2_algo_type
grub_luks2_token_systemd_tpm2_algo_type_t;
+
+enum grub_luks2_token_systemd_tpm2_pcr_bank_type
+{
+ LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA256,
+ LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA1
+};
+
+typedef enum grub_luks2_token_systemd_tpm2_pcr_bank_type
grub_luks2_token_systemd_tpm2_pcr_bank_type_t;
+
+struct grub_luks2_token
+{
+ grub_uint64_t idx;
+ grub_luks2_token_type_t type;
+ grub_uint64_t keyslots;
+ union
+ {
+ struct
+ {
+ grub_uint32_t pcr_mask;
+ grub_luks2_token_systemd_tpm2_pcr_bank_type_t pcr_bank;
+ grub_luks2_token_systemd_tpm2_algo_type_t primary_alg;
+ const char *base64_blob;
+ const char *hex_policy_hash;
+ const char *base64_srk;
+ } systemd_tpm2;
+ } u;
+};
+typedef struct grub_luks2_token grub_luks2_token_t;
+
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t blocksize,
grub_size_t blocknumbers);
@@ -258,11 +306,88 @@ luks2_parse_digest (grub_luks2_digest_t *out, const
grub_json_t *digest)
return GRUB_ERR_NONE;
}
+static grub_err_t
+luks2_parse_token (grub_luks2_token_t *out, const grub_json_t *token)
+{
+ grub_json_t keyslots, pcrs, o;
+ grub_size_t i, size;
+ grub_uint64_t bit;
+ const char *type;
+ const char *pcr_bank;
+ const char *alg;
+
+ if (grub_json_getstring (&type, token, "type"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest type");
+ else if (grub_strcmp (type, "systemd-tpm2"))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported digest type %s",
type);
+ out->type = LUKS2_TOKEN_TYPE_SYSTEMD_TPM2;
+
+ if (grub_json_getvalue (&keyslots, token, "keyslots") ||
+ grub_json_getvalue (&pcrs, token, "tpm2-pcrs") ||
+ grub_json_getstring (&pcr_bank, token, "tpm2-pcr-bank") ||
+ grub_json_getstring (&out->u.systemd_tpm2.base64_blob, token,
"tpm2-blob") ||
+ grub_json_getstring (&out->u.systemd_tpm2.hex_policy_hash, token,
"tpm2-policy-hash"))
+ {
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing token parameters");
+ }
+
+ if (grub_json_getsize (&size, &pcrs))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "token references no pcrs");
+
+ out->u.systemd_tpm2.pcr_mask = 0;
+ for (i = 0; i < size; i++)
+ {
+ if (grub_json_getchild (&o, &pcrs, i) ||
+ grub_json_getuint64 (&bit, &o, NULL) || bit >= TPM_MAX_PCRS)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid pcr");
+ out->u.systemd_tpm2.pcr_mask |= (1 << bit);
+ }
+
+ if (grub_strcmp (pcr_bank, "sha256") == 0)
+ out->u.systemd_tpm2.pcr_bank =
LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA256;
+ else if (grub_strcmp (pcr_bank, "sha1") == 0)
+ out->u.systemd_tpm2.pcr_bank = LUKS2_TOKEN_SYSTEMD_TPM2_PCR_BANK_TYPE_SHA1;
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported pcr-bank type %s",
pcr_bank);
+
+ // Default is hardcoded ECC
+ if (grub_json_getstring (&alg, token, "tpm2-primary-alg") == GRUB_ERR_NONE)
+ {
+ if (grub_strcmp (alg, "ecc") == 0)
+ out->u.systemd_tpm2.primary_alg =
LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC;
+ else if (grub_strcmp (alg, "rsa") == 0)
+ out->u.systemd_tpm2.primary_alg =
LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_RSA;
+ else
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported algo type %s",
alg);
+ }
+ else
+ out->u.systemd_tpm2.primary_alg = LUKS2_TOKEN_SYSTEMD_TPM2_ALGO_TYPE_ECC;
+
+ if (grub_json_getsize (&size, &keyslots))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "token references no keyslots");
+ out->keyslots = 0;
+ for (i = 0; i < size; i++)
+ {
+ if (grub_json_getchild (&o, &keyslots, i) ||
+ grub_json_getuint64 (&bit, &o, NULL))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot");
+ out->keyslots |= (1 << bit);
+ }
+
+ /* Optional SRK */
+ if (grub_json_getstring (&out->u.systemd_tpm2.base64_srk, token, "tpm2_srk"))
+ {
+ out->u.systemd_tpm2.base64_srk = NULL;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d,
grub_luks2_segment_t *s,
- const grub_json_t *root, grub_size_t keyslot_json_idx)
+ grub_luks2_token_t *t, const grub_json_t *root, grub_size_t
keyslot_json_idx)
{
- grub_json_t keyslots, keyslot, digests, digest, segments, segment;
+ grub_json_t keyslots, keyslot, digests, digest, segments, segment, tokens,
token;
grub_size_t json_idx, size;
/* Get nth keyslot */
@@ -309,6 +434,27 @@ luks2_get_keyslot (grub_luks2_keyslot_t *k,
grub_luks2_digest_t *d, grub_luks2_s
if (json_idx == size)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%"
PRIuGRUB_UINT64_T "\"", d->idx);
+ if (t == NULL)
+ return GRUB_ERR_NONE;
+
+ /* Get token that matches the keyslot. */
+ if (grub_json_getvalue (&tokens, root, "tokens") ||
+ grub_json_getsize (&size, &tokens))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get tokens");
+ for (json_idx = 0; json_idx < size; json_idx++)
+ {
+ if (grub_json_getchild (&token, &tokens, json_idx) ||
+ grub_json_getuint64 (&t->idx, &token, NULL) ||
+ grub_json_getchild (&token, &token, 0) ||
+ luks2_parse_token (t, &token))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse token index
%" PRIuGRUB_SIZE, json_idx);
+
+ if ((t->keyslots & (1 << k->idx)))
+ break;
+ }
+ if (json_idx == size)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No token for keyslot \"%"
PRIuGRUB_UINT64_T "\"", k->idx);
+
return GRUB_ERR_NONE;
}
@@ -626,7 +772,7 @@ luks2_recover_key (grub_disk_t source,
typeof (source->total_sectors) max_crypt_sectors = 0;
grub_errno = GRUB_ERR_NONE;
- ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx);
+ ret = luks2_get_keyslot (&keyslot, &digest, &segment, NULL, json,
json_idx);
if (ret)
{
/*
--
2.39.5
_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel