From 03ce3384fd8a427c8b3df49191b1f5a71ae4a6aff93b0752feaf4108d9bd0e9e Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 26 Apr 2023 03:19:58 +0000 Subject: [PATCH] Accepting request 1082613 from home:gary_lin:branches:Base:System - Update TPM 2.0 key unsealing patches OBS-URL: https://build.opensuse.org/request/show/1082613 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=452 --- ...tectors-Add-key-protectors-framework.patch | 65 +- ...pes-structures-and-command-constants.patch | 45 +- ...input-parameters-of-TPM2_EvictContro.patch | 73 - ...0002-tpm2-Add-TPM-Software-Stack-TSS.patch | 828 +++---- ...Add-more-marshal-unmarshal-functions.patch | 24 +- ...-input-arguments-of-TPM2-functions-a.patch | 696 ------ 0003-protectors-Add-TPM2-Key-Protector.patch | 2002 +++++++++++++++++ ...03-tpm2-Implement-more-TPM2-commands.patch | 20 +- ...2-resend-the-command-on-TPM_RC_RETRY.patch | 68 - ...04-cryptodisk-Support-key-protectors.patch | 0 0004-tpm2-Support-authorized-policy.patch | 142 ++ ... 0005-util-grub-protect-Add-new-tool.patch | 819 ++++--- ...-command-parameters-of-TPM2-commands.patch | 86 - ...ssing-authorization-command-for-TPM2.patch | 30 - ...w-some-command-parameters-to-be-NULL.patch | 47 - ...pm2-remove-the-unnecessary-variables.patch | 44 - ...le-reading-unmarshal-functions-gener.patch | 135 -- 0012-protectors-Add-TPM2-Key-Protector.patch | 977 -------- ...tialize-the-PCR-selection-list-early.patch | 103 - ...unsealing-key-with-authorized-policy.patch | 794 ------- fix-tpm2-build.patch | 38 - grub-read-pcr.patch | 2 +- grub-unseal-debug.patch | 41 - grub2.changes | 43 + grub2.spec | 43 +- tpm-protector-dont-measure-sealed-key.patch | 15 - tpm-protector-export-secret-key.patch | 138 -- 27 files changed, 3259 insertions(+), 4059 deletions(-) rename 0010-protectors-Add-key-protectors-framework.patch => 0001-protectors-Add-key-protectors-framework.patch (75%) rename 0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch => 0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch (84%) delete mode 100644 0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch rename 0011-tpm2-Add-TPM-Software-Stack-TSS.patch => 0002-tpm2-Add-TPM-Software-Stack-TSS.patch (81%) rename 0005-tpm2-add-more-marshal-unmarshal-functions.patch => 0002-tpm2-Add-more-marshal-unmarshal-functions.patch (95%) delete mode 100644 0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch create mode 100644 0003-protectors-Add-TPM2-Key-Protector.patch rename 0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch => 0003-tpm2-Implement-more-TPM2-commands.patch (97%) delete mode 100644 0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch rename 0013-cryptodisk-Support-key-protectors.patch => 0004-cryptodisk-Support-key-protectors.patch (100%) create mode 100644 0004-tpm2-Support-authorized-policy.patch rename 0014-util-grub-protect-Add-new-tool.patch => 0005-util-grub-protect-Add-new-tool.patch (62%) delete mode 100644 0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch delete mode 100644 0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch delete mode 100644 0008-tpm2-allow-some-command-parameters-to-be-NULL.patch delete mode 100644 0009-tpm2-remove-the-unnecessary-variables.patch delete mode 100644 0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch delete mode 100644 0012-protectors-Add-TPM2-Key-Protector.patch delete mode 100644 0012-tpm2-initialize-the-PCR-selection-list-early.patch delete mode 100644 0013-tpm2-support-unsealing-key-with-authorized-policy.patch delete mode 100644 fix-tpm2-build.patch delete mode 100644 grub-unseal-debug.patch delete mode 100644 tpm-protector-dont-measure-sealed-key.patch delete mode 100644 tpm-protector-export-secret-key.patch diff --git a/0010-protectors-Add-key-protectors-framework.patch b/0001-protectors-Add-key-protectors-framework.patch similarity index 75% rename from 0010-protectors-Add-key-protectors-framework.patch rename to 0001-protectors-Add-key-protectors-framework.patch index 84a5612..1d40095 100644 --- a/0010-protectors-Add-key-protectors-framework.patch +++ b/0001-protectors-Add-key-protectors-framework.patch @@ -1,21 +1,22 @@ -From 2d959549857305d5e4d95a19a0850885f85179d6 Mon Sep 17 00:00:00 2001 +From 5affde982dea827580e36ccc658e439397f51ce8 Mon Sep 17 00:00:00 2001 From: Hernan Gatta Date: Tue, 1 Feb 2022 05:02:53 -0800 -Subject: [PATCH 10/14] protectors: Add key protectors framework +Subject: [PATCH 1/5] protectors: Add key protectors framework -A key protector encapsulates functionality to retrieve an unlocking key for a -fully-encrypted disk from a specific source. A key protector module registers -itself with the key protectors framework when it is loaded and unregisters when -unloaded. Additionally, a key protector may accept parameters that describe how -it should operate. +A key protector encapsulates functionality to retrieve an unlocking key +for a fully-encrypted disk from a specific source. A key protector +module registers itself with the key protectors framework when it is +loaded and unregisters when unloaded. Additionally, a key protector may +accept parameters that describe how it should operate. -The key protectors framework, besides offering registration and unregistration -functions, also offers a one-stop routine for finding and invoking a key -protector by name. If a key protector with the specified name exists and if an -unlocking key is successfully retrieved by it, the function returns to the -caller the retrieved key and its length. +The key protectors framework, besides offering registration and +unregistration functions, also offers a one-stop routine for finding and +invoking a key protector by name. If a key protector with the specified +name exists and if an unlocking key is successfully retrieved by it, the +function returns to the caller the retrieved key and its length. Signed-off-by: Hernan Gatta +Signed-off-by: Gary Lin --- grub-core/Makefile.am | 1 + grub-core/Makefile.core.def | 1 + @@ -26,7 +27,7 @@ Signed-off-by: Hernan Gatta create mode 100644 include/grub/protector.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am -index de241f0d04..dc07ba6f87 100644 +index 80e7a83ed..79d17a3d2 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -90,6 +90,7 @@ endif @@ -38,10 +39,10 @@ index de241f0d04..dc07ba6f87 100644 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index f3140815b8..b0001a33cf 100644 +index d83c9f7b6..0335d9add 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def -@@ -138,6 +138,7 @@ kernel = { +@@ -144,6 +144,7 @@ kernel = { common = kern/misc.c; common = kern/parser.c; common = kern/partition.c; @@ -51,7 +52,7 @@ index f3140815b8..b0001a33cf 100644 common = kern/term.c; diff --git a/grub-core/kern/protectors.c b/grub-core/kern/protectors.c new file mode 100644 -index 0000000000..21954dfa48 +index 000000000..5ee059565 --- /dev/null +++ b/grub-core/kern/protectors.c @@ -0,0 +1,75 @@ @@ -83,16 +84,16 @@ index 0000000000..21954dfa48 +grub_err_t +grub_key_protector_register (struct grub_key_protector *protector) +{ -+ if (!protector || !protector->name || !grub_strlen(protector->name)) ++ if (protector == NULL || protector->name == NULL || grub_strlen(protector->name) == 0) + return GRUB_ERR_BAD_ARGUMENT; + + if (grub_key_protectors && + grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), -+ protector->name)) ++ protector->name)) + return GRUB_ERR_BAD_ARGUMENT; + + grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors), -+ GRUB_AS_LIST (protector)); ++ GRUB_AS_LIST (protector)); + + return GRUB_ERR_NONE; +} @@ -100,7 +101,7 @@ index 0000000000..21954dfa48 +grub_err_t +grub_key_protector_unregister (struct grub_key_protector *protector) +{ -+ if (!protector) ++ if (protector == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + grub_list_remove (GRUB_AS_LIST (protector)); @@ -110,29 +111,29 @@ index 0000000000..21954dfa48 + +grub_err_t +grub_key_protector_recover_key (const char *protector, grub_uint8_t **key, -+ grub_size_t *key_size) ++ grub_size_t *key_size) +{ + struct grub_key_protector *kp = NULL; + -+ if (!grub_key_protectors) ++ if (grub_key_protectors == NULL) + return GRUB_ERR_OUT_OF_RANGE; + -+ if (!protector || !grub_strlen (protector)) ++ if (protector == NULL || grub_strlen (protector) == 0) + return GRUB_ERR_BAD_ARGUMENT; + + kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), -+ protector); -+ if (!kp) ++ protector); ++ if (kp == NULL) + return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("A key protector with name '%s' could not be found. " -+ "Is the name spelled correctly and is the " -+ "corresponding module loaded?"), protector); ++ N_("A key protector with name '%s' could not be found. " ++ "Is the name spelled correctly and is the " ++ "corresponding module loaded?"), protector); + + return kp->recover_key (key, key_size); +} diff --git a/include/grub/protector.h b/include/grub/protector.h new file mode 100644 -index 0000000000..179020a344 +index 000000000..3d9f69bce --- /dev/null +++ b/include/grub/protector.h @@ -0,0 +1,48 @@ @@ -180,10 +181,10 @@ index 0000000000..179020a344 + +grub_err_t +EXPORT_FUNC (grub_key_protector_recover_key) (const char *protector, -+ grub_uint8_t **key, -+ grub_size_t *key_size); ++ grub_uint8_t **key, ++ grub_size_t *key_size); + +#endif /* ! GRUB_PROTECTOR_HEADER */ -- -2.34.1 +2.35.3 diff --git a/0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch b/0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch similarity index 84% rename from 0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch rename to 0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch index 8938544..dca72f6 100644 --- a/0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch +++ b/0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch @@ -1,10 +1,9 @@ -From 69a5cedcb206ca931ac2c2763c283954751d7072 Mon Sep 17 00:00:00 2001 +From 5a417f32f1afe0ffca7f5cbff67145a157b1589b Mon Sep 17 00:00:00 2001 From: Gary Lin Date: Tue, 7 Feb 2023 18:31:12 +0800 -Subject: [PATCH 04/13] tpm2: add new TPM2 types, structures, and command - constants +Subject: [PATCH 1/4] tpm2: Add TPM2 types, structures, and command constants -Add new TPM2 types and structures as the preparation to support the +Add new TPM2 types and structures as the preparation to support authorized policy. * New types: @@ -18,20 +17,20 @@ authorized policy. * New command constants: TPM_CC_LoadExternal, TPM_CC_HashSequenceStart, TPM_CC_SequenceUpdate, - TPM_CC_SequenceComplete, TPM_CC_VerifySignature, + TPM_CC_SequenceComplete, TPM_CC_Hash, TPM_CC_VerifySignature, TPM_CC_PolicyAuthorize Signed-off-by: Gary Lin --- - include/grub/tpm2/internal/structs.h | 60 ++++++++++++++++++++++++++++ - include/grub/tpm2/internal/types.h | 42 ++++++++++++------- - 2 files changed, 88 insertions(+), 14 deletions(-) + include/grub/tpm2/internal/structs.h | 86 ++++++++++++++++++++++++++++ + include/grub/tpm2/internal/types.h | 42 +++++++++----- + 2 files changed, 114 insertions(+), 14 deletions(-) diff --git a/include/grub/tpm2/internal/structs.h b/include/grub/tpm2/internal/structs.h -index 75bf99ec8..50090892c 100644 +index 72d71eb70..db9eb6cf6 100644 --- a/include/grub/tpm2/internal/structs.h +++ b/include/grub/tpm2/internal/structs.h -@@ -672,4 +672,64 @@ struct TPMT_TK_CREATION +@@ -672,4 +672,90 @@ struct TPMT_TK_CREATION }; typedef struct TPMT_TK_CREATION TPMT_TK_CREATION; @@ -87,6 +86,32 @@ index 75bf99ec8..50090892c 100644 +}; +typedef struct TPMT_SIGNATURE TPMT_SIGNATURE; + ++static inline TPMI_ALG_HASH ++TPMT_SIGNATURE_get_hash_alg (TPMT_SIGNATURE *sig) ++{ ++ switch (sig->sigAlg) ++ { ++ case TPM_ALG_RSASSA: ++ return sig->signature.rsassa.hash; ++ case TPM_ALG_RSAPSS: ++ return sig->signature.rsapss.hash; ++ case TPM_ALG_ECDSA: ++ return sig->signature.ecdsa.hash; ++ case TPM_ALG_ECDAA: ++ return sig->signature.ecdaa.hash; ++ case TPM_ALG_SM2: ++ return sig->signature.sm2.hash; ++ case TPM_ALG_ECSCHNORR: ++ return sig->signature.ecschnorr.hash; ++ case TPM_ALG_HMAC: ++ return sig->signature.hmac.hashAlg; ++ default: ++ break; ++ } ++ ++ return TPM_ALG_NULL; ++} ++ +/* TPMT_TK_VERIFIED Structure */ +struct TPMT_TK_VERIFIED { + TPM_ST tag; diff --git a/0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch b/0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch deleted file mode 100644 index af5a93f..0000000 --- a/0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch +++ /dev/null @@ -1,73 +0,0 @@ -From bc5ecda21bb612f786f614623da782d7ad6d8325 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Tue, 7 Feb 2023 18:01:31 +0800 -Subject: [PATCH 01/13] tpm2: adjust the input parameters of TPM2_EvictControl - -Per "TCG TPM2 Part3 Commands", 'persistentHandle' of TPM2_EvictControl -is in the parameter area, i.e. after the authorization command. Adjust -the order of the arguments to match the spec definition. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/tpm2.c | 2 +- - include/grub/tpm2/internal/functions.h | 2 +- - util/grub-protect.c | 8 ++++---- - 3 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 2407a844d..1cd969d5d 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -662,8 +662,8 @@ TPM2_Create (TPMI_DH_OBJECT parentHandle, - TPM_RC - TPM2_EvictControl (TPMI_RH_PROVISION auth, - TPMI_DH_OBJECT objectHandle, -- TPMI_DH_PERSISTENT persistentHandle, - const TPMS_AUTH_COMMAND *authCommand, -+ TPMI_DH_PERSISTENT persistentHandle, - TPMS_AUTH_RESPONSE *authResponse) - { - struct grub_tpm2_buffer in; -diff --git a/include/grub/tpm2/internal/functions.h b/include/grub/tpm2/internal/functions.h -index a1c71fae5..f08b45ed2 100644 ---- a/include/grub/tpm2/internal/functions.h -+++ b/include/grub/tpm2/internal/functions.h -@@ -110,8 +110,8 @@ TPM2_Create (TPMI_DH_OBJECT parentHandle, - TPM_RC - TPM2_EvictControl (TPMI_RH_PROVISION auth, - TPMI_DH_OBJECT objectHandle, -- TPMI_DH_PERSISTENT persistentHandle, - const TPMS_AUTH_COMMAND *authCommand, -+ TPMI_DH_PERSISTENT persistentHandle, - TPMS_AUTH_RESPONSE *authResponse); - - #endif /* ! GRUB_TPM2_INTERNAL_FUNCTIONS_HEADER */ -diff --git a/util/grub-protect.c b/util/grub-protect.c -index d03be3e90..5ff76b613 100644 ---- a/util/grub-protect.c -+++ b/util/grub-protect.c -@@ -695,8 +695,8 @@ grub_protect_tpm2_get_srk (struct grub_protect_args *args, TPM_HANDLE *srk) - /* Persist SRK */ - if (args->tpm2_persist) - { -- rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, args->tpm2_srk, -- &authCommand, NULL); -+ rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, &authCommand, -+ args->tpm2_srk, NULL); - if (rc == TPM_RC_SUCCESS) - { - TPM2_FlushContext (srkHandle); -@@ -877,8 +877,8 @@ grub_protect_tpm2_remove (struct grub_protect_args *args) - /* Evict SRK */ - authCommand.sessionHandle = TPM_RS_PW; - -- rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, args->tpm2_srk, -- &authCommand, NULL); -+ rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, &authCommand, -+ args->tpm2_srk, NULL); - if (rc != TPM_RC_SUCCESS) - { - fprintf (stderr, --- -2.35.3 - diff --git a/0011-tpm2-Add-TPM-Software-Stack-TSS.patch b/0002-tpm2-Add-TPM-Software-Stack-TSS.patch similarity index 81% rename from 0011-tpm2-Add-TPM-Software-Stack-TSS.patch rename to 0002-tpm2-Add-TPM-Software-Stack-TSS.patch index 9c0755c..278c413 100644 --- a/0011-tpm2-Add-TPM-Software-Stack-TSS.patch +++ b/0002-tpm2-Add-TPM-Software-Stack-TSS.patch @@ -1,46 +1,48 @@ -From 65f937752d51b81fb830d4c6177975d395be9346 Mon Sep 17 00:00:00 2001 +From a4f5c4aa64e0484b08dcb9b7798395c55ca45ead Mon Sep 17 00:00:00 2001 From: Hernan Gatta Date: Tue, 1 Feb 2022 05:02:54 -0800 -Subject: [PATCH 11/14] tpm2: Add TPM Software Stack (TSS) +Subject: [PATCH 2/5] tpm2: Add TPM Software Stack (TSS) -A Trusted Platform Module (TPM) Software Stack (TSS) provides logic to compose, -submit, and parse TPM commands and responses. +A Trusted Platform Module (TPM) Software Stack (TSS) provides logic to +compose, submit, and parse TPM commands and responses. -A limited number of TPM commands may be accessed via the EFI TCG2 protocol. This -protocol exposes functionality that is primarily geared toward TPM usage within -the context of Secure Boot. For all other TPM commands, however, such as sealing -and unsealing, this protocol does not provide any help, with the exception of -passthrough command submission. +A limited number of TPM commands may be accessed via the EFI TCG2 +protocol. This protocol exposes functionality that is primarily geared +toward TPM usage within the context of Secure Boot. For all other TPM +commands, however, such as sealing and unsealing, this protocol does not +provide any help, with the exception of passthrough command submission. -The SubmitCommand method allows a caller to send raw commands to the system's -TPM and to receive the corresponding response. These command/response pairs are -formatted using the TPM wire protocol. To construct commands in this way, and to -parse the TPM's response, it is necessary to, first, possess knowledge of the -various TPM structures, and, two, of the TPM wire protocol itself. +The SubmitCommand method allows a caller to send raw commands to the +system's TPM and to receive the corresponding response. These +command/response pairs are formatted using the TPM wire protocol. To +construct commands in this way, and to parse the TPM's response, it is +necessary to, first, possess knowledge of the various TPM structures, and, +second, of the TPM wire protocol itself. -As such, this patch includes a set of header files that define the necessary TPM -structures and TSS functions, implementations of various TPM2_* functions -(inventoried below), and logic to write and read command and response buffers, -respectively, using the TPM wire protocol. +As such, this patch includes a set of header files that define the +necessary TPM structures and TSS functions, implementations of various +TPM2_* functions (inventoried below), and logic to write and read command +and response buffers, respectively, using the TPM wire protocol. Functions: TPM2_Create, TPM2_CreatePrimary, TPM2_EvictControl, TPM2_FlushContext, TPM2_Load, TPM2_PCR_Read, TPM2_PolicyGetDigest, TPM2_PolicyPCR, TPM2_ReadPublic, TPM2_StartAuthSession, TPM2_Unseal. Signed-off-by: Hernan Gatta +Signed-off-by: Gary Lin --- grub-core/tpm2/buffer.c | 145 +++++ grub-core/tpm2/mu.c | 807 +++++++++++++++++++++++++ grub-core/tpm2/tcg2.c | 143 +++++ - grub-core/tpm2/tpm2.c | 711 ++++++++++++++++++++++ + grub-core/tpm2/tpm2.c | 761 +++++++++++++++++++++++ include/grub/tpm2/buffer.h | 65 ++ include/grub/tpm2/internal/functions.h | 117 ++++ include/grub/tpm2/internal/structs.h | 675 +++++++++++++++++++++ include/grub/tpm2/internal/types.h | 372 ++++++++++++ include/grub/tpm2/mu.h | 292 +++++++++ include/grub/tpm2/tcg2.h | 34 ++ - include/grub/tpm2/tpm2.h | 38 ++ - 11 files changed, 3399 insertions(+) + include/grub/tpm2/tpm2.h | 34 ++ + 11 files changed, 3445 insertions(+) create mode 100644 grub-core/tpm2/buffer.c create mode 100644 grub-core/tpm2/mu.c create mode 100644 grub-core/tpm2/tcg2.c @@ -55,7 +57,7 @@ Signed-off-by: Hernan Gatta diff --git a/grub-core/tpm2/buffer.c b/grub-core/tpm2/buffer.c new file mode 100644 -index 0000000000..fee42d5a9e +index 000000000..cb9f29497 --- /dev/null +++ b/grub-core/tpm2/buffer.c @@ -0,0 +1,145 @@ @@ -91,7 +93,7 @@ index 0000000000..fee42d5a9e + +void +grub_tpm2_buffer_pack (grub_tpm2_buffer_t buffer, const void* data, -+ grub_size_t size) ++ grub_size_t size) +{ + grub_uint32_t r = buffer->cap - buffer->size; + @@ -117,20 +119,20 @@ index 0000000000..fee42d5a9e +void +grub_tpm2_buffer_pack_u16 (grub_tpm2_buffer_t buffer, grub_uint16_t value) +{ -+ grub_uint16_t tmp = grub_swap_bytes16 (value); ++ grub_uint16_t tmp = grub_cpu_to_be16 (value); + grub_tpm2_buffer_pack (buffer, (const char*) &tmp, sizeof (tmp)); +} + +void +grub_tpm2_buffer_pack_u32 (grub_tpm2_buffer_t buffer, grub_uint32_t value) +{ -+ grub_uint32_t tmp = grub_swap_bytes32 (value); ++ grub_uint32_t tmp = grub_cpu_to_be32 (value); + grub_tpm2_buffer_pack (buffer, (const char*) &tmp, sizeof (tmp)); +} + +void +grub_tpm2_buffer_unpack (grub_tpm2_buffer_t buffer, void* data, -+ grub_size_t size) ++ grub_size_t size) +{ + grub_uint32_t r = buffer->size - buffer->offset; + @@ -182,7 +184,7 @@ index 0000000000..fee42d5a9e + + grub_memcpy (&tmp, &buffer->data[buffer->offset], sizeof (tmp)); + buffer->offset += sizeof (tmp); -+ *value = grub_swap_bytes16 (tmp); ++ *value = grub_be_to_cpu16 (tmp); +} + +void @@ -202,11 +204,11 @@ index 0000000000..fee42d5a9e + + grub_memcpy (&tmp, &buffer->data[buffer->offset], sizeof (tmp)); + buffer->offset += sizeof (tmp); -+ *value = grub_swap_bytes32 (tmp); ++ *value = grub_be_to_cpu32 (tmp); +} diff --git a/grub-core/tpm2/mu.c b/grub-core/tpm2/mu.c new file mode 100644 -index 0000000000..c5f5c7b5f8 +index 000000000..1617f37cd --- /dev/null +++ b/grub-core/tpm2/mu.c @@ -0,0 +1,807 @@ @@ -233,7 +235,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buffer, -+ const TPMS_AUTH_COMMAND* authCommand) ++ const TPMS_AUTH_COMMAND* authCommand) +{ + grub_uint32_t start; + grub_uint32_t tmp; @@ -245,24 +247,24 @@ index 0000000000..c5f5c7b5f8 + + grub_tpm2_buffer_pack_u16 (buffer, authCommand->nonce.size); + grub_tpm2_buffer_pack (buffer, authCommand->nonce.buffer, -+ authCommand->nonce.size); ++ authCommand->nonce.size); + + grub_tpm2_buffer_pack_u8 (buffer, -+ *((const grub_uint8_t*) &authCommand->sessionAttributes)); ++ *((const grub_uint8_t*) &authCommand->sessionAttributes)); + + grub_tpm2_buffer_pack_u16 (buffer, authCommand->hmac.size); + grub_tpm2_buffer_pack (buffer, authCommand->hmac.buffer, -+ authCommand->hmac.size); ++ authCommand->hmac.size); + -+ tmp = grub_swap_bytes32 (buffer->size - start); ++ tmp = grub_cpu_to_be32 (buffer->size - start); + grub_memcpy (&buffer->data[start - sizeof (grub_uint32_t)], &tmp, -+ sizeof (tmp)); ++ sizeof (tmp)); +} + +void +grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buffer, -+ grub_uint16_t size, -+ const grub_uint8_t* b) ++ const grub_uint16_t size, ++ const grub_uint8_t* b) +{ + grub_tpm2_buffer_pack_u16 (buffer, size); + @@ -272,8 +274,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_KEY_BITS *p) ++ const TPMI_ALG_SYM_OBJECT algorithm, ++ const TPMU_SYM_KEY_BITS *p) +{ + switch (algorithm) + { @@ -290,8 +292,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_MODE *p) ++ const TPMI_ALG_SYM_OBJECT algorithm, ++ const TPMU_SYM_MODE *p) +{ + switch (algorithm) + { @@ -308,7 +310,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_SYM_DEF *p) ++ const TPMT_SYM_DEF *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->algorithm); + grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (buffer, p->algorithm, &p->keyBits); @@ -317,7 +319,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buffer, -+ const TPMS_PCR_SELECTION* pcrSelection) ++ const TPMS_PCR_SELECTION* pcrSelection) +{ + grub_tpm2_buffer_pack_u16 (buffer, pcrSelection->hash); + grub_tpm2_buffer_pack_u8 (buffer, pcrSelection->sizeOfSelect); @@ -328,25 +330,25 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buffer, -+ const TPML_PCR_SELECTION* pcrSelection) ++ const TPML_PCR_SELECTION* pcrSelection) +{ + grub_tpm2_buffer_pack_u32 (buffer, pcrSelection->count); + + for (grub_uint32_t i = 0; i < pcrSelection->count; i++) + grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (buffer, -+ &pcrSelection->pcrSelections[i]); ++ &pcrSelection->pcrSelections[i]); +} + +void +grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buffer, -+ const TPMA_OBJECT *p) ++ const TPMA_OBJECT *p) +{ + grub_tpm2_buffer_pack_u32 (buffer, *((const grub_uint32_t*) p)); +} + +void +grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_SCHEME_XOR *p) ++ const TPMS_SCHEME_XOR *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg); + grub_tpm2_buffer_pack_u16 (buffer, p->kdf); @@ -354,15 +356,15 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_SCHEME_HMAC *p) ++ const TPMS_SCHEME_HMAC *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg); +} + +void +grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ TPMU_SCHEME_KEYEDHASH *p) ++ const TPMI_ALG_KEYEDHASH_SCHEME scheme, ++ const TPMU_SCHEME_KEYEDHASH *p) +{ + switch (scheme) + { @@ -382,7 +384,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_KEYEDHASH_SCHEME *p) ++ const TPMT_KEYEDHASH_SCHEME *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->scheme); + grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (buffer, p->scheme, &p->details); @@ -390,14 +392,14 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_KEYEDHASH_PARMS *p) ++ const TPMS_KEYEDHASH_PARMS *p) +{ + grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (buffer, &p->scheme); +} + +void +grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_SYM_DEF_OBJECT *p) ++ const TPMT_SYM_DEF_OBJECT *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->algorithm); + grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (buffer, p->algorithm, &p->keyBits); @@ -406,8 +408,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_RSA_DECRYPT scheme, -+ TPMU_ASYM_SCHEME *p __attribute__ ((unused))) ++ const TPMI_ALG_RSA_DECRYPT scheme, ++ const TPMU_ASYM_SCHEME *p __attribute__ ((unused))) +{ + switch (scheme) + { @@ -422,7 +424,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_RSA_SCHEME *p) ++ const TPMT_RSA_SCHEME *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->scheme); + grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (buffer, p->scheme, &p->details); @@ -430,7 +432,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_RSA_PARMS *p) ++ const TPMS_RSA_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->symmetric); + grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (buffer, &p->scheme); @@ -440,14 +442,14 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_SYMCIPHER_PARMS *p) ++ const TPMS_SYMCIPHER_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->sym); +} + +void +grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_ECC_SCHEME *p) ++ const TPMT_ECC_SCHEME *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->scheme); + grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (buffer, p->scheme, &p->details); @@ -455,8 +457,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_KDF scheme, -+ TPMU_KDF_SCHEME *p) ++ const TPMI_ALG_KDF scheme, ++ const TPMU_KDF_SCHEME *p) +{ + switch (scheme) + { @@ -482,7 +484,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_KDF_SCHEME *p) ++ const TPMT_KDF_SCHEME *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->scheme); + grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (buffer, p->scheme, &p->details); @@ -490,7 +492,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_ECC_PARMS *p) ++ const TPMS_ECC_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->symmetric); + grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (buffer, &p->scheme); @@ -500,8 +502,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer, -+ grub_uint32_t type, -+ TPMU_PUBLIC_PARMS *p) ++ const grub_uint32_t type, ++ const TPMU_PUBLIC_PARMS *p) +{ + switch (type) + { @@ -525,7 +527,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_ECC_POINT *p) ++ const TPMS_ECC_POINT *p) +{ + grub_tpm2_mu_TPM2B_Marshal (buffer, p->x.size, p->x.buffer); + grub_tpm2_mu_TPM2B_Marshal (buffer, p->y.size, p->y.buffer); @@ -533,14 +535,14 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_PUBLIC type, -+ TPMU_PUBLIC_ID *p) ++ const TPMI_ALG_PUBLIC type, ++ const TPMU_PUBLIC_ID *p) +{ + switch(type) + { + case TPM_ALG_KEYEDHASH: + grub_tpm2_mu_TPM2B_Marshal (buffer, p->keyedHash.size, -+ p->keyedHash.buffer); ++ p->keyedHash.buffer); + break; + case TPM_ALG_SYMCIPHER: + grub_tpm2_mu_TPM2B_Marshal (buffer, p->sym.size, p->sym.buffer); @@ -556,7 +558,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, -+ TPMT_PUBLIC *p) ++ const TPMT_PUBLIC *p) +{ + grub_tpm2_buffer_pack_u16 (buffer, p->type); + grub_tpm2_buffer_pack_u16 (buffer, p->nameAlg); @@ -568,7 +570,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, -+ TPM2B_PUBLIC *p) ++ const TPM2B_PUBLIC *p) +{ + grub_uint32_t start; + grub_uint16_t size; @@ -579,9 +581,9 @@ index 0000000000..c5f5c7b5f8 + + start = buffer->size; + grub_tpm2_mu_TPMT_PUBLIC_Marshal (buffer, &p->publicArea); -+ size = grub_swap_bytes16 (buffer->size - start); ++ size = grub_cpu_to_be16 (buffer->size - start); + grub_memcpy (&buffer->data[start - sizeof (grub_uint16_t)], &size, -+ sizeof (size)); ++ sizeof (size)); + } + else + grub_tpm2_buffer_pack_u16 (buffer, 0); @@ -589,7 +591,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, -+ TPMS_SENSITIVE_CREATE *p) ++ const TPMS_SENSITIVE_CREATE *p) +{ + grub_tpm2_mu_TPM2B_Marshal (buffer, p->userAuth.size, p->userAuth.buffer); + grub_tpm2_mu_TPM2B_Marshal (buffer, p->data.size, p->data.buffer); @@ -597,7 +599,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, -+ TPM2B_SENSITIVE_CREATE *sensitiveCreate) ++ const TPM2B_SENSITIVE_CREATE *sensitiveCreate) +{ + grub_uint32_t start; + grub_uint16_t size; @@ -607,11 +609,11 @@ index 0000000000..c5f5c7b5f8 + grub_tpm2_buffer_pack_u16 (buffer, sensitiveCreate->size); + start = buffer->size; + grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (buffer, -+ &sensitiveCreate->sensitive); -+ size = grub_swap_bytes16 (buffer->size - start); ++ &sensitiveCreate->sensitive); ++ size = grub_cpu_to_be16 (buffer->size - start); + + grub_memcpy (&buffer->data[start - sizeof (grub_uint16_t)], &size, -+ sizeof (size)); ++ sizeof (size)); + } + else + grub_tpm2_buffer_pack_u16 (buffer, 0); @@ -619,7 +621,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPM2B* p) ++ TPM2B* p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->size); + @@ -629,7 +631,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_AUTH_RESPONSE* p) ++ TPMS_AUTH_RESPONSE* p) +{ + grub_uint8_t tmp; + grub_uint32_t tmp32; @@ -651,28 +653,28 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPM2B_DIGEST* digest) ++ TPM2B_DIGEST* digest) +{ + grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*)digest); +} + +void +grub_tpm2_mu_TPMA_OBJECT_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMA_OBJECT *p) ++ TPMA_OBJECT *p) +{ + grub_tpm2_buffer_unpack_u32 (buffer, (grub_uint32_t*)p); +} + +void +grub_tpm2_mu_TPMS_SCHEME_HMAC_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_SCHEME_HMAC *p) ++ TPMS_SCHEME_HMAC *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->hashAlg); +} + +void +grub_tpm2_mu_TPMS_SCHEME_XOR_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_SCHEME_XOR *p) ++ TPMS_SCHEME_XOR *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->hashAlg); + grub_tpm2_buffer_unpack_u16 (buffer, &p->kdf); @@ -680,8 +682,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ TPMU_SCHEME_KEYEDHASH *p) ++ TPMI_ALG_KEYEDHASH_SCHEME scheme, ++ TPMU_SCHEME_KEYEDHASH *p) +{ + switch (scheme) + { @@ -701,7 +703,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_KEYEDHASH_SCHEME *p) ++ TPMT_KEYEDHASH_SCHEME *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->scheme); + grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Unmarshal (buffer, p->scheme, &p->details); @@ -709,15 +711,15 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_KEYEDHASH_PARMS *p) ++ TPMS_KEYEDHASH_PARMS *p) +{ + grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Unmarshal (buffer, &p->scheme); +} + +void +grub_tpm2_mu_TPMU_SYM_KEY_BITS_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_KEY_BITS *p) ++ TPMI_ALG_SYM_OBJECT algorithm, ++ TPMU_SYM_KEY_BITS *p) +{ + switch (algorithm) + { @@ -734,8 +736,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_SYM_MODE_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_MODE *p) ++ TPMI_ALG_SYM_OBJECT algorithm, ++ TPMU_SYM_MODE *p) +{ + switch (algorithm) + { @@ -752,7 +754,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_SYM_DEF_OBJECT *p) ++ TPMT_SYM_DEF_OBJECT *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->algorithm); + grub_tpm2_mu_TPMU_SYM_KEY_BITS_Unmarshal (buffer, p->algorithm, &p->keyBits); @@ -761,15 +763,15 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_SYMCIPHER_PARMS *p) ++ TPMS_SYMCIPHER_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (buffer, &p->sym); +} + +void +grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_RSA_DECRYPT scheme, -+ TPMU_ASYM_SCHEME *p __attribute__((unused))) ++ TPMI_ALG_RSA_DECRYPT scheme, ++ TPMU_ASYM_SCHEME *p __attribute__((unused))) +{ + switch (scheme) + { @@ -784,7 +786,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_RSA_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_RSA_SCHEME *p) ++ TPMT_RSA_SCHEME *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->scheme); + grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (buffer, p->scheme, &p->details); @@ -792,7 +794,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_RSA_PARMS_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_RSA_PARMS *p) ++ TPMS_RSA_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (buffer, &p->symmetric); + grub_tpm2_mu_TPMT_RSA_SCHEME_Unmarshal (buffer, &p->scheme); @@ -802,7 +804,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_ECC_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_ECC_SCHEME *p) ++ TPMT_ECC_SCHEME *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->scheme); + grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (buffer, p->scheme, &p->details); @@ -810,8 +812,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_KDF scheme, -+ TPMU_KDF_SCHEME *p) ++ TPMI_ALG_KDF scheme, ++ TPMU_KDF_SCHEME *p) +{ + switch (scheme) + { @@ -837,7 +839,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_KDF_SCHEME *p) ++ TPMT_KDF_SCHEME *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->scheme); + grub_tpm2_mu_TPMU_KDF_SCHEME_Unmarshal (buffer, p->scheme, &p->details); @@ -845,7 +847,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_ECC_PARMS_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_ECC_PARMS *p) ++ TPMS_ECC_PARMS *p) +{ + grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (buffer, &p->symmetric); + grub_tpm2_mu_TPMT_ECC_SCHEME_Unmarshal (buffer, &p->scheme ); @@ -855,8 +857,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_PUBLIC_PARMS_Unmarshal (grub_tpm2_buffer_t buffer, -+ grub_uint32_t type, -+ TPMU_PUBLIC_PARMS *p) ++ grub_uint32_t type, ++ TPMU_PUBLIC_PARMS *p) +{ + switch (type) + { @@ -880,7 +882,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_ECC_POINT *p) ++ TPMS_ECC_POINT *p) +{ + grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->x); + grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->y); @@ -888,8 +890,8 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMU_PUBLIC_ID_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMI_ALG_PUBLIC type, -+ TPMU_PUBLIC_ID *p) ++ TPMI_ALG_PUBLIC type, ++ TPMU_PUBLIC_ID *p) +{ + switch(type) + { @@ -910,7 +912,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMT_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_PUBLIC *p) ++ TPMT_PUBLIC *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->type); + grub_tpm2_buffer_unpack_u16 (buffer, &p->nameAlg); @@ -922,7 +924,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPM2B_PUBLIC *p) ++ TPM2B_PUBLIC *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->size); + grub_tpm2_mu_TPMT_PUBLIC_Unmarshal (buffer, &p->publicArea); @@ -930,7 +932,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_NV_PUBLIC *p) ++ TPMS_NV_PUBLIC *p) +{ + grub_tpm2_buffer_unpack_u32 (buffer, &p->nvIndex); + grub_tpm2_buffer_unpack_u16 (buffer, &p->nameAlg); @@ -941,7 +943,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPM2B_NV_PUBLIC *p) ++ TPM2B_NV_PUBLIC *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->size); + grub_tpm2_mu_TPMS_NV_PUBLIC_Unmarshal (buffer, &p->nvPublic); @@ -949,7 +951,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPM2B_NAME *n) ++ TPM2B_NAME *n) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &n->size); + grub_tpm2_buffer_unpack (buffer, n->name, n->size); @@ -957,7 +959,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_TAGGED_PROPERTY* property) ++ TPMS_TAGGED_PROPERTY* property) +{ + grub_tpm2_buffer_unpack_u32 (buffer, &property->property); + grub_tpm2_buffer_unpack_u32 (buffer, &property->value); @@ -965,22 +967,22 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_CAPABILITY_DATA_tpmProperties_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMS_CAPABILITY_DATA* capabilityData) ++ TPMS_CAPABILITY_DATA* capabilityData) +{ + grub_tpm2_buffer_unpack_u32 (buffer, -+ &capabilityData->data.tpmProperties.count); ++ &capabilityData->data.tpmProperties.count); + + if (buffer->error) + return; + + for (grub_uint32_t i = 0; i < capabilityData->data.tpmProperties.count; i++) + grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (buffer, -+ &capabilityData->data.tpmProperties.tpmProperty[i]); ++ &capabilityData->data.tpmProperties.tpmProperty[i]); +} + +void +grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer, -+ TPMT_TK_CREATION *p) ++ TPMT_TK_CREATION *p) +{ + grub_tpm2_buffer_unpack_u16 (buffer, &p->tag); + grub_tpm2_buffer_unpack_u32 (buffer, &p->hierarchy); @@ -989,7 +991,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_PCR_SELECTION* pcrSelection) ++ TPMS_PCR_SELECTION* pcrSelection) +{ + grub_tpm2_buffer_unpack_u16 (buf, &pcrSelection->hash); + grub_tpm2_buffer_unpack_u8 (buf, &pcrSelection->sizeOfSelect); @@ -1000,7 +1002,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, -+ TPML_PCR_SELECTION* pcrSelection) ++ TPML_PCR_SELECTION* pcrSelection) +{ + grub_tpm2_buffer_unpack_u32 (buf, &pcrSelection->count); + @@ -1010,7 +1012,7 @@ index 0000000000..c5f5c7b5f8 + +void +grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf, -+ TPML_DIGEST* digest) ++ TPML_DIGEST* digest) +{ + grub_tpm2_buffer_unpack_u32 (buf, &digest->count); + @@ -1019,7 +1021,7 @@ index 0000000000..c5f5c7b5f8 +} diff --git a/grub-core/tpm2/tcg2.c b/grub-core/tpm2/tcg2.c new file mode 100644 -index 0000000000..44837218a2 +index 000000000..d350e3a24 --- /dev/null +++ b/grub-core/tpm2/tcg2.c @@ -0,0 +1,143 @@ @@ -1049,7 +1051,7 @@ index 0000000000..44837218a2 + +static grub_err_t +grub_tcg2_get_caps (grub_efi_tpm2_protocol_t *protocol, int *tpm2, -+ grub_size_t *max_output_size) ++ grub_size_t *max_output_size) +{ + grub_efi_status_t status; + @@ -1096,14 +1098,14 @@ index 0000000000..44837218a2 + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL, -+ &num_handles); ++ &num_handles); + if (!handles || !num_handles) + return err; + + tpm2_handle = handles[0]; + + tpm2_protocol = grub_efi_open_protocol (tpm2_handle, &tpm2_guid, -+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); ++ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!tpm2_protocol) + goto exit; + @@ -1144,9 +1146,9 @@ index 0000000000..44837218a2 + +grub_err_t +grub_tcg2_submit_command (grub_size_t input_size, -+ grub_uint8_t *input, -+ grub_size_t output_size, -+ grub_uint8_t *output) ++ grub_uint8_t *input, ++ grub_size_t output_size, ++ grub_uint8_t *output) +{ + grub_err_t err; + grub_efi_status_t status; @@ -1160,7 +1162,7 @@ index 0000000000..44837218a2 + return err; + + status = efi_call_5 (protocol->submit_command, protocol, input_size, input, -+ output_size, output); ++ output_size, output); + if (status != GRUB_EFI_SUCCESS) + return GRUB_ERR_INVALID_COMMAND; + @@ -1168,10 +1170,10 @@ index 0000000000..44837218a2 +} diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c new file mode 100644 -index 0000000000..2407a844d2 +index 000000000..d67699a24 --- /dev/null +++ b/grub-core/tpm2/tpm2.c -@@ -0,0 +1,711 @@ +@@ -0,0 +1,761 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation @@ -1199,11 +1201,11 @@ index 0000000000..2407a844d2 +#include + +static TPM_RC -+grub_tpm2_submit_command (TPMI_ST_COMMAND_TAG tag, -+ TPM_CC commandCode, -+ TPM_RC* responseCode, -+ const struct grub_tpm2_buffer* in, -+ struct grub_tpm2_buffer* out) ++grub_tpm2_submit_command_real (const TPMI_ST_COMMAND_TAG tag, ++ const TPM_CC commandCode, ++ TPM_RC *responseCode, ++ const struct grub_tpm2_buffer *in, ++ struct grub_tpm2_buffer *out) +{ + grub_err_t err; + struct grub_tpm2_buffer buf; @@ -1223,7 +1225,7 @@ index 0000000000..2407a844d2 + + command_size = grub_swap_bytes32 (buf.size); + grub_memcpy (&buf.data[sizeof (grub_uint16_t)], &command_size, -+ sizeof (command_size)); ++ sizeof (command_size)); + + /* Stay within output block limits */ + err = grub_tcg2_get_max_output_size (&max_output_size); @@ -1232,13 +1234,13 @@ index 0000000000..2407a844d2 + + /* Submit */ + err = grub_tcg2_submit_command (buf.size, buf.data, max_output_size, -+ out->data); ++ out->data); + if (err) + return TPM_RC_FAILURE; + + /* Unmarshal*/ + out->size = sizeof (grub_uint16_t) + sizeof (grub_uint32_t) + -+ sizeof (grub_uint32_t); ++ sizeof (grub_uint32_t); + grub_tpm2_buffer_unpack_u16 (out, &tag_out); + grub_tpm2_buffer_unpack_u32 (out, &command_size); + grub_tpm2_buffer_unpack_u32 (out, responseCode); @@ -1249,20 +1251,43 @@ index 0000000000..2407a844d2 + return TPM_RC_SUCCESS; +} + ++static TPM_RC ++grub_tpm2_submit_command (const TPMI_ST_COMMAND_TAG tag, ++ const TPM_CC commandCode, ++ TPM_RC *responseCode, ++ const struct grub_tpm2_buffer *in, ++ struct grub_tpm2_buffer *out) ++{ ++ TPM_RC err; ++ int retry_cnt = 0; ++ ++ /* Catch TPM_RC_RETRY and send the command again */ ++ do { ++ err = grub_tpm2_submit_command_real (tag, commandCode, responseCode, ++ in, out); ++ if (*responseCode != TPM_RC_RETRY) ++ break; ++ ++ retry_cnt++; ++ } while (retry_cnt < 3); ++ ++ return err; ++} ++ +TPM_RC -+TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_CREATE *inSensitive, -+ TPM2B_PUBLIC *inPublic, -+ TPM2B_DATA *outsideInfo, -+ TPML_PCR_SELECTION *creationPCR, -+ TPM_HANDLE *objectHandle, -+ TPM2B_PUBLIC *outPublic, -+ TPM2B_CREATION_DATA *creationData, -+ TPM2B_DIGEST *creationHash, -+ TPMT_TK_CREATION *creationTicket, -+ TPM2B_NAME *name, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_SENSITIVE_CREATE *inSensitive, ++ const TPM2B_PUBLIC *inPublic, ++ const TPM2B_DATA *outsideInfo, ++ const TPML_PCR_SELECTION *creationPCR, ++ TPM_HANDLE *objectHandle, ++ TPM2B_PUBLIC *outPublic, ++ TPM2B_CREATION_DATA *creationData, ++ TPM2B_DIGEST *creationHash, ++ TPMT_TK_CREATION *creationTicket, ++ TPM2B_NAME *name, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1278,6 +1303,9 @@ index 0000000000..2407a844d2 + TPM_RC responseCode; + grub_uint32_t parameterSize; + ++ if (!inSensitive || !inPublic || !outsideInfo || !creationPCR) ++ return TPM_RC_VALUE; ++ + if (!objectHandle) + objectHandle = &objectHandleTmp; + if (!outPublic) @@ -1315,7 +1343,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_CreatePrimary, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1339,17 +1367,17 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_StartAuthSession (TPMI_DH_OBJECT tpmKey, -+ TPMI_DH_ENTITY bind, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_NONCE *nonceCaller, -+ TPM2B_ENCRYPTED_SECRET *encryptedSalt, -+ TPM_SE sessionType, -+ TPMT_SYM_DEF *symmetric, -+ TPMI_ALG_HASH authHash, -+ TPMI_SH_AUTH_SESSION *sessionHandle, -+ TPM2B_NONCE *nonceTpm, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, ++ const TPMI_DH_ENTITY bind, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_NONCE *nonceCaller, ++ const TPM2B_ENCRYPTED_SECRET *encryptedSalt, ++ const TPM_SE sessionType, ++ const TPMT_SYM_DEF *symmetric, ++ const TPMI_ALG_HASH authHash, ++ TPMI_SH_AUTH_SESSION *sessionHandle, ++ TPM2B_NONCE *nonceTpm, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1361,6 +1389,13 @@ index 0000000000..2407a844d2 + TPM_RC responseCode; + grub_uint32_t param_size; + ++ if (!nonceCaller || !symmetric) ++ return TPM_RC_VALUE; ++ ++ if (tpmKey == TPM_RH_NULL && ++ (encryptedSalt && encryptedSalt->size != 0)) ++ return TPM_RC_VALUE; ++ + if (!sessionHandle) + sessionHandle = &sessionHandleTmp; + if (!nonceTpm) @@ -1379,7 +1414,10 @@ index 0000000000..2407a844d2 + if (tag == TPM_ST_SESSIONS) + grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); + grub_tpm2_mu_TPM2B_Marshal (&in, nonceCaller->size, nonceCaller->buffer); -+ grub_tpm2_mu_TPM2B_Marshal (&in, encryptedSalt->size, encryptedSalt->secret); ++ if (encryptedSalt) ++ grub_tpm2_mu_TPM2B_Marshal (&in, encryptedSalt->size, encryptedSalt->secret); ++ else ++ grub_tpm2_buffer_pack_u16 (&in, 0); + grub_tpm2_buffer_pack_u8 (&in, sessionType); + grub_tpm2_mu_TPMT_SYM_DEF_Marshal (&in, symmetric); + grub_tpm2_buffer_pack_u16 (&in, authHash); @@ -1389,7 +1427,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_StartAuthSession, &responseCode, -+ &in, &out); ++ &in, &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1409,11 +1447,11 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_PolicyPCR (TPMI_SH_POLICY policySessions, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_DIGEST *pcrDigest, -+ TPML_PCR_SELECTION *pcrs, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_PolicyPCR (const TPMI_SH_POLICY policySessions, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_DIGEST *pcrDigest, ++ const TPML_PCR_SELECTION *pcrs, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1423,6 +1461,9 @@ index 0000000000..2407a844d2 + TPM_RC responseCode; + grub_uint32_t param_size; + ++ if (!pcrs) ++ return TPM_RC_VALUE; ++ + if (!authResponse) + authResponse = &authResponseTmp; + @@ -1433,7 +1474,10 @@ index 0000000000..2407a844d2 + grub_tpm2_buffer_pack_u32 (&in, policySessions); + if (tag == TPM_ST_SESSIONS) + grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); -+ grub_tpm2_mu_TPM2B_Marshal (&in, pcrDigest->size, pcrDigest->buffer); ++ if (pcrDigest) ++ grub_tpm2_mu_TPM2B_Marshal (&in, pcrDigest->size, pcrDigest->buffer); ++ else ++ grub_tpm2_buffer_pack_u16 (&in, 0); + grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, pcrs); + if (in.error) + return TPM_RC_FAILURE; @@ -1441,7 +1485,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyPCR, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1459,9 +1503,9 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_ReadPublic (TPMI_DH_OBJECT objectHandle, -+ const TPMS_AUTH_COMMAND* authCommand, -+ TPM2B_PUBLIC *outPublic) ++TPM2_ReadPublic (const TPMI_DH_OBJECT objectHandle, ++ const TPMS_AUTH_COMMAND* authCommand, ++ TPM2B_PUBLIC *outPublic) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1479,7 +1523,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_ReadPublic, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1496,13 +1540,13 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_Load (TPMI_DH_OBJECT parent_handle, -+ TPMS_AUTH_COMMAND const *authCommand, -+ TPM2B_PRIVATE *inPrivate, -+ TPM2B_PUBLIC *inPublic, -+ TPM_HANDLE *objectHandle, -+ TPM2B_NAME *name, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_Load (const TPMI_DH_OBJECT parent_handle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_PRIVATE *inPrivate, ++ const TPM2B_PUBLIC *inPublic, ++ TPM_HANDLE *objectHandle, ++ TPM2B_NAME *name, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1514,6 +1558,9 @@ index 0000000000..2407a844d2 + TPM_RC responseCode; + grub_uint32_t param_size; + ++ if (!inPrivate || !inPublic) ++ return TPM_RC_VALUE; ++ + if (!objectHandle) + objectHandle = &objectHandleTmp; + if (!name) @@ -1557,10 +1604,10 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_Unseal (TPMI_DH_OBJECT itemHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_DATA *outData, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_Unseal (const TPMI_DH_OBJECT itemHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ TPM2B_SENSITIVE_DATA *outData, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1608,7 +1655,7 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_FlushContext (TPMI_DH_CONTEXT handle) ++TPM2_FlushContext (const TPMI_DH_CONTEXT handle) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1624,7 +1671,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (TPM_ST_NO_SESSIONS, TPM_CC_FlushContext, -+ &responseCode, &in, &out); ++ &responseCode, &in, &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1639,11 +1686,11 @@ index 0000000000..2407a844d2 + +TPM_RC +TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, -+ TPML_PCR_SELECTION *pcrSelectionIn, -+ grub_uint32_t *pcrUpdateCounter, -+ TPML_PCR_SELECTION *pcrSelectionOut, -+ TPML_DIGEST *pcrValues, -+ TPMS_AUTH_RESPONSE *authResponse) ++ const TPML_PCR_SELECTION *pcrSelectionIn, ++ grub_uint32_t *pcrUpdateCounter, ++ TPML_PCR_SELECTION *pcrSelectionOut, ++ TPML_DIGEST *pcrValues, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1657,7 +1704,7 @@ index 0000000000..2407a844d2 + grub_uint32_t parameterSize; + + if (!pcrSelectionIn) -+ return TPM_RC_FAILURE; ++ return TPM_RC_VALUE; + + if (!pcrUpdateCounter) + pcrUpdateCounter = &pcrUpdateCounterTmp; @@ -1670,6 +1717,8 @@ index 0000000000..2407a844d2 + + /* Marshal */ + grub_tpm2_buffer_init (&in); ++ if (authCommand) ++ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); + grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, pcrSelectionIn); + if (in.error) + return TPM_RC_FAILURE; @@ -1677,7 +1726,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_PCR_Read, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1698,10 +1747,10 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_PolicyGetDigest (TPMI_SH_POLICY policySession, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_DIGEST *policyDigest, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_PolicyGetDigest (const TPMI_SH_POLICY policySession, ++ const TPMS_AUTH_COMMAND *authCommand, ++ TPM2B_DIGEST *policyDigest, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + TPM_RC rc; + struct grub_tpm2_buffer in; @@ -1731,7 +1780,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_PolicyGetDigest, &responseCode, -+ &in, &out); ++ &in, &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1750,18 +1799,18 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_Create (TPMI_DH_OBJECT parentHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_CREATE *inSensitive, -+ TPM2B_PUBLIC *inPublic, -+ TPM2B_DATA *outsideInfo, -+ TPML_PCR_SELECTION *creationPCR, -+ TPM2B_PRIVATE *outPrivate, -+ TPM2B_PUBLIC *outPublic, -+ TPM2B_CREATION_DATA *creationData, -+ TPM2B_DIGEST *creationHash, -+ TPMT_TK_CREATION *creationTicket, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_Create (const TPMI_DH_OBJECT parentHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_SENSITIVE_CREATE *inSensitive, ++ const TPM2B_PUBLIC *inPublic, ++ const TPM2B_DATA *outsideInfo, ++ const TPML_PCR_SELECTION *creationPCR, ++ TPM2B_PRIVATE *outPrivate, ++ TPM2B_PUBLIC *outPublic, ++ TPM2B_CREATION_DATA *creationData, ++ TPM2B_DIGEST *creationHash, ++ TPMT_TK_CREATION *creationTicket, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + struct grub_tpm2_buffer in; + struct grub_tpm2_buffer out; @@ -1776,6 +1825,9 @@ index 0000000000..2407a844d2 + TPM_RC rc; + grub_uint32_t parameterSize; + ++ if (!inSensitive || !inPublic || !outsideInfo || !creationPCR) ++ return TPM_RC_VALUE; ++ + if (!outPrivate) + outPrivate = &outPrivateTmp; + if (!outPublic) @@ -1811,7 +1863,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_Create, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1834,11 +1886,11 @@ index 0000000000..2407a844d2 +} + +TPM_RC -+TPM2_EvictControl (TPMI_RH_PROVISION auth, -+ TPMI_DH_OBJECT objectHandle, -+ TPMI_DH_PERSISTENT persistentHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPMS_AUTH_RESPONSE *authResponse) ++TPM2_EvictControl (const TPMI_RH_PROVISION auth, ++ const TPMI_DH_OBJECT objectHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPMI_DH_PERSISTENT persistentHandle, ++ TPMS_AUTH_RESPONSE *authResponse) +{ + struct grub_tpm2_buffer in; + struct grub_tpm2_buffer out; @@ -1866,7 +1918,7 @@ index 0000000000..2407a844d2 + /* Submit */ + grub_tpm2_buffer_init (&out); + rc = grub_tpm2_submit_command (tag, TPM_CC_EvictControl, &responseCode, &in, -+ &out); ++ &out); + if (rc != TPM_RC_SUCCESS) + return rc; + if (responseCode != TPM_RC_SUCCESS) @@ -1885,7 +1937,7 @@ index 0000000000..2407a844d2 +} diff --git a/include/grub/tpm2/buffer.h b/include/grub/tpm2/buffer.h new file mode 100644 -index 0000000000..ad05393add +index 000000000..87dcd8d6c --- /dev/null +++ b/include/grub/tpm2/buffer.h @@ -0,0 +1,65 @@ @@ -1929,7 +1981,7 @@ index 0000000000..ad05393add + +void +grub_tpm2_buffer_pack (grub_tpm2_buffer_t buffer, const void* data, -+ grub_size_t size); ++ grub_size_t size); + +void +grub_tpm2_buffer_pack_u8 (grub_tpm2_buffer_t buffer, grub_uint8_t value); @@ -1942,7 +1994,7 @@ index 0000000000..ad05393add + +void +grub_tpm2_buffer_unpack (grub_tpm2_buffer_t buffer, void* data, -+ grub_size_t size); ++ grub_size_t size); + +void +grub_tpm2_buffer_unpack_u8 (grub_tpm2_buffer_t buffer, grub_uint8_t* value); @@ -1956,7 +2008,7 @@ index 0000000000..ad05393add +#endif /* ! GRUB_TPM2_BUFFER_HEADER */ diff --git a/include/grub/tpm2/internal/functions.h b/include/grub/tpm2/internal/functions.h new file mode 100644 -index 0000000000..a1c71fae51 +index 000000000..9380f26a2 --- /dev/null +++ b/include/grub/tpm2/internal/functions.h @@ -0,0 +1,117 @@ @@ -1984,102 +2036,102 @@ index 0000000000..a1c71fae51 +#include + +TPM_RC -+TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_CREATE *inSensitive, -+ TPM2B_PUBLIC *inPublic, -+ TPM2B_DATA *outsideInfo, -+ TPML_PCR_SELECTION *creationPCR, -+ TPM_HANDLE *objectHandle, -+ TPM2B_PUBLIC *outPublic, -+ TPM2B_CREATION_DATA *creationData, -+ TPM2B_DIGEST *creationHash, -+ TPMT_TK_CREATION *creationTicket, -+ TPM2B_NAME *name, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_SENSITIVE_CREATE *inSensitive, ++ const TPM2B_PUBLIC *inPublic, ++ const TPM2B_DATA *outsideInfo, ++ const TPML_PCR_SELECTION *creationPCR, ++ TPM_HANDLE *objectHandle, ++ TPM2B_PUBLIC *outPublic, ++ TPM2B_CREATION_DATA *creationData, ++ TPM2B_DIGEST *creationHash, ++ TPMT_TK_CREATION *creationTicket, ++ TPM2B_NAME *name, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_StartAuthSession (TPMI_DH_OBJECT tpmKey, -+ TPMI_DH_ENTITY bind, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_NONCE *nonceCaller, -+ TPM2B_ENCRYPTED_SECRET *encryptedSalt, -+ TPM_SE sessionType, -+ TPMT_SYM_DEF *symmetric, -+ TPMI_ALG_HASH authHash, -+ TPMI_SH_AUTH_SESSION *sessionHandle, -+ TPM2B_NONCE *nonceTpm, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, ++ const TPMI_DH_ENTITY bind, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_NONCE *nonceCaller, ++ const TPM2B_ENCRYPTED_SECRET *encryptedSalt, ++ const TPM_SE sessionType, ++ const TPMT_SYM_DEF *symmetric, ++ const TPMI_ALG_HASH authHash, ++ TPMI_SH_AUTH_SESSION *sessionHandle, ++ TPM2B_NONCE *nonceTpm, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_PolicyPCR (TPMI_SH_POLICY policySession, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_DIGEST *pcrDigest, -+ TPML_PCR_SELECTION *pcrs, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_PolicyPCR (const TPMI_SH_POLICY policySession, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_DIGEST *pcrDigest, ++ const TPML_PCR_SELECTION *pcrs, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_ReadPublic (TPMI_DH_OBJECT objectHandle, -+ const TPMS_AUTH_COMMAND* authCommand, -+ TPM2B_PUBLIC *outPublic); ++TPM2_ReadPublic (const TPMI_DH_OBJECT objectHandle, ++ const TPMS_AUTH_COMMAND* authCommand, ++ TPM2B_PUBLIC *outPublic); + +TPM_RC -+TPM2_Load (TPMI_DH_OBJECT parent_handle, -+ TPMS_AUTH_COMMAND const *authCommand, -+ TPM2B_PRIVATE *inPrivate, -+ TPM2B_PUBLIC *inPublic, -+ TPM_HANDLE *objectHandle, -+ TPM2B_NAME *name, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_Load (const TPMI_DH_OBJECT parent_handle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_PRIVATE *inPrivate, ++ const TPM2B_PUBLIC *inPublic, ++ TPM_HANDLE *objectHandle, ++ TPM2B_NAME *name, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_Unseal (TPMI_DH_OBJECT item_handle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_DATA *outData, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_Unseal (const TPMI_DH_OBJECT item_handle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ TPM2B_SENSITIVE_DATA *outData, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_FlushContext (TPMI_DH_CONTEXT handle); ++TPM2_FlushContext (const TPMI_DH_CONTEXT handle); + +TPM_RC +TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, -+ TPML_PCR_SELECTION *pcrSelectionIn, -+ grub_uint32_t *pcrUpdateCounter, -+ TPML_PCR_SELECTION *pcrSelectionOut, -+ TPML_DIGEST *pcrValues, -+ TPMS_AUTH_RESPONSE *authResponse); ++ const TPML_PCR_SELECTION *pcrSelectionIn, ++ grub_uint32_t *pcrUpdateCounter, ++ TPML_PCR_SELECTION *pcrSelectionOut, ++ TPML_DIGEST *pcrValues, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_PolicyGetDigest (TPMI_SH_POLICY policySession, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_DIGEST *policyDigest, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_PolicyGetDigest (const TPMI_SH_POLICY policySession, ++ const TPMS_AUTH_COMMAND *authCommand, ++ TPM2B_DIGEST *policyDigest, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_Create (TPMI_DH_OBJECT parentHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPM2B_SENSITIVE_CREATE *inSensitive, -+ TPM2B_PUBLIC *inPublic, -+ TPM2B_DATA *outsideInfo, -+ TPML_PCR_SELECTION *creationPCR, -+ TPM2B_PRIVATE *outPrivate, -+ TPM2B_PUBLIC *outPublic, -+ TPM2B_CREATION_DATA *creationData, -+ TPM2B_DIGEST *creationHash, -+ TPMT_TK_CREATION *creationTicket, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_Create (const TPMI_DH_OBJECT parentHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPM2B_SENSITIVE_CREATE *inSensitive, ++ const TPM2B_PUBLIC *inPublic, ++ const TPM2B_DATA *outsideInfo, ++ const TPML_PCR_SELECTION *creationPCR, ++ TPM2B_PRIVATE *outPrivate, ++ TPM2B_PUBLIC *outPublic, ++ TPM2B_CREATION_DATA *creationData, ++ TPM2B_DIGEST *creationHash, ++ TPMT_TK_CREATION *creationTicket, ++ TPMS_AUTH_RESPONSE *authResponse); + +TPM_RC -+TPM2_EvictControl (TPMI_RH_PROVISION auth, -+ TPMI_DH_OBJECT objectHandle, -+ TPMI_DH_PERSISTENT persistentHandle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ TPMS_AUTH_RESPONSE *authResponse); ++TPM2_EvictControl (const TPMI_RH_PROVISION auth, ++ const TPMI_DH_OBJECT objectHandle, ++ const TPMS_AUTH_COMMAND *authCommand, ++ const TPMI_DH_PERSISTENT persistentHandle, ++ TPMS_AUTH_RESPONSE *authResponse); + +#endif /* ! GRUB_TPM2_INTERNAL_FUNCTIONS_HEADER */ diff --git a/include/grub/tpm2/internal/structs.h b/include/grub/tpm2/internal/structs.h new file mode 100644 -index 0000000000..75bf99ec8a +index 000000000..72d71eb70 --- /dev/null +++ b/include/grub/tpm2/internal/structs.h @@ -0,0 +1,675 @@ @@ -2533,7 +2585,7 @@ index 0000000000..75bf99ec8a +typedef union TPMU_PUBLIC_ID TPMU_PUBLIC_ID; + +/* TPMT_PUBLIC Structure */ -+struct TPMT_PUBLIC ++struct TPMT_PUBLIC +{ + TPMI_ALG_PUBLIC type; + TPMI_ALG_HASH nameAlg; @@ -2760,7 +2812,7 @@ index 0000000000..75bf99ec8a +#endif /* ! GRUB_TPM2_INTERNAL_STRUCTS_HEADER */ diff --git a/include/grub/tpm2/internal/types.h b/include/grub/tpm2/internal/types.h new file mode 100644 -index 0000000000..9714f75d4f +index 000000000..9714f75d4 --- /dev/null +++ b/include/grub/tpm2/internal/types.h @@ -0,0 +1,372 @@ @@ -3138,7 +3190,7 @@ index 0000000000..9714f75d4f +#endif /* ! GRUB_TPM2_INTERNAL_TYPES_HEADER */ diff --git a/include/grub/tpm2/mu.h b/include/grub/tpm2/mu.h new file mode 100644 -index 0000000000..4f4058f9d6 +index 000000000..c545976db --- /dev/null +++ b/include/grub/tpm2/mu.h @@ -0,0 +1,292 @@ @@ -3168,275 +3220,275 @@ index 0000000000..4f4058f9d6 + +void +grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buf, -+ const TPMS_AUTH_COMMAND* authCommand); ++ const TPMS_AUTH_COMMAND* authCommand); + +void +grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buf, -+ grub_uint16_t size, -+ const grub_uint8_t* buffer); ++ const grub_uint16_t size, ++ const grub_uint8_t* buffer); + +void +grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_KEY_BITS *p); ++ const TPMI_ALG_SYM_OBJECT algorithm, ++ const TPMU_SYM_KEY_BITS *p); + +void +grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_MODE *p); ++ const TPMI_ALG_SYM_OBJECT algorithm, ++ const TPMU_SYM_MODE *p); + +void +grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_SYM_DEF *p); ++ const TPMT_SYM_DEF *p); + +void +grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buf, -+ const TPMS_PCR_SELECTION* pcrSelection); ++ const TPMS_PCR_SELECTION* pcrSelection); + +void +grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buf, -+ const TPML_PCR_SELECTION* pcrSelection); ++ const TPML_PCR_SELECTION* pcrSelection); + +void +grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buf, -+ const TPMA_OBJECT *p); ++ const TPMA_OBJECT *p); + +void +grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_SCHEME_XOR *p); ++ const TPMS_SCHEME_XOR *p); + +void +grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_SCHEME_HMAC *p); ++ const TPMS_SCHEME_HMAC *p); + +void +grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ TPMU_SCHEME_KEYEDHASH *p); ++ const TPMI_ALG_KEYEDHASH_SCHEME scheme, ++ const TPMU_SCHEME_KEYEDHASH *p); + +void +grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_KEYEDHASH_SCHEME *p); ++ const TPMT_KEYEDHASH_SCHEME *p); + +void +grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_KEYEDHASH_PARMS *p); ++ const TPMS_KEYEDHASH_PARMS *p); + +void +grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_SYM_DEF_OBJECT *p); ++ const TPMT_SYM_DEF_OBJECT *p); + +void +grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_RSA_DECRYPT scheme, -+ TPMU_ASYM_SCHEME *p); ++ const TPMI_ALG_RSA_DECRYPT scheme, ++ const TPMU_ASYM_SCHEME *p); + +void +grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_RSA_SCHEME *p); ++ const TPMT_RSA_SCHEME *p); + +void +grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_RSA_PARMS *p); ++ const TPMS_RSA_PARMS *p); + +void +grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_SYMCIPHER_PARMS *p); ++ const TPMS_SYMCIPHER_PARMS *p); + +void +grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_ECC_SCHEME *p); ++ const TPMT_ECC_SCHEME *p); + +void +grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_KDF scheme, -+ TPMU_KDF_SCHEME *p); ++ const TPMI_ALG_KDF scheme, ++ const TPMU_KDF_SCHEME *p); + +void +grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_KDF_SCHEME *p); ++ const TPMT_KDF_SCHEME *p); + +void +grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_ECC_PARMS *p); ++ const TPMS_ECC_PARMS *p); + +void +grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buf, -+ grub_uint32_t type, -+ TPMU_PUBLIC_PARMS *p); ++ const grub_uint32_t type, ++ const TPMU_PUBLIC_PARMS *p); + +void +grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_ECC_POINT *p); ++ const TPMS_ECC_POINT *p); + +void +grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_PUBLIC type, -+ TPMU_PUBLIC_ID *p); ++ const TPMI_ALG_PUBLIC type, ++ const TPMU_PUBLIC_ID *p); + +void +grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buf, -+ TPMT_PUBLIC *p); ++ const TPMT_PUBLIC *p); + +void +grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buf, -+ TPM2B_PUBLIC *p); ++ const TPM2B_PUBLIC *p); + +void +grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf, -+ TPMS_SENSITIVE_CREATE *p); ++ const TPMS_SENSITIVE_CREATE *p); + +void +grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf, -+ TPM2B_SENSITIVE_CREATE *sensitiveCreate); ++ const TPM2B_SENSITIVE_CREATE *sensitiveCreate); + +void +grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buf, -+ TPM2B* p); ++ TPM2B* p); + +void +grub_tpm2_mu_TPMS_AUTH_RESPONSE_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_AUTH_RESPONSE* p); ++ TPMS_AUTH_RESPONSE* p); + +void +grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (grub_tpm2_buffer_t buf, -+ TPM2B_DIGEST* digest); ++ TPM2B_DIGEST* digest); + +void +grub_tpm2_mu_TPMA_OBJECT_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMA_OBJECT *p); ++ TPMA_OBJECT *p); + +void +grub_tpm2_mu_TPMS_SCHEME_HMAC_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_SCHEME_HMAC *p); ++ TPMS_SCHEME_HMAC *p); + +void +grub_tpm2_mu_TPMS_SCHEME_XOR_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_SCHEME_XOR *p); ++ TPMS_SCHEME_XOR *p); + +void +grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ TPMU_SCHEME_KEYEDHASH *p); ++ TPMI_ALG_KEYEDHASH_SCHEME scheme, ++ TPMU_SCHEME_KEYEDHASH *p); + +void +grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_KEYEDHASH_SCHEME *p); ++ TPMT_KEYEDHASH_SCHEME *p); + +void +grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_KEYEDHASH_PARMS *p); ++ TPMS_KEYEDHASH_PARMS *p); + +void +grub_tpm2_mu_TPMU_SYM_KEY_BITS_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_KEY_BITS *p); ++ TPMI_ALG_SYM_OBJECT algorithm, ++ TPMU_SYM_KEY_BITS *p); + +void +grub_tpm2_mu_TPMU_SYM_MODE_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_SYM_OBJECT algorithm, -+ TPMU_SYM_MODE *p); ++ TPMI_ALG_SYM_OBJECT algorithm, ++ TPMU_SYM_MODE *p); + +void +grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_SYM_DEF_OBJECT *p); ++ TPMT_SYM_DEF_OBJECT *p); + +void +grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_SYMCIPHER_PARMS *p); ++ TPMS_SYMCIPHER_PARMS *p); + +void +grub_tpm2_mu_TPMU_ASYM_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_RSA_DECRYPT scheme, -+ TPMU_ASYM_SCHEME *p); ++ TPMI_ALG_RSA_DECRYPT scheme, ++ TPMU_ASYM_SCHEME *p); + +void +grub_tpm2_mu_TPMT_RSA_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_RSA_SCHEME *p); ++ TPMT_RSA_SCHEME *p); + +void +grub_tpm2_mu_TPMS_RSA_PARMS_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_RSA_PARMS *p); ++ TPMS_RSA_PARMS *p); + +void +grub_tpm2_mu_TPMT_ECC_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_ECC_SCHEME *p); ++ TPMT_ECC_SCHEME *p); + +void +grub_tpm2_mu_TPMU_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_KDF scheme, -+ TPMU_KDF_SCHEME *p); ++ TPMI_ALG_KDF scheme, ++ TPMU_KDF_SCHEME *p); + +void +grub_tpm2_mu_TPMT_KDF_SCHEME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_KDF_SCHEME *p); ++ TPMT_KDF_SCHEME *p); + +void +grub_tpm2_mu_TPMS_ECC_PARMS_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_ECC_PARMS *p); ++ TPMS_ECC_PARMS *p); + +void +grub_tpm2_mu_TPMU_PUBLIC_PARMS_Unmarshal (grub_tpm2_buffer_t buf, -+ grub_uint32_t type, -+ TPMU_PUBLIC_PARMS *p); ++ grub_uint32_t type, ++ TPMU_PUBLIC_PARMS *p); + +void +grub_tpm2_mu_TPMS_ECC_POINT_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_ECC_POINT *p); ++ TPMS_ECC_POINT *p); + +void +grub_tpm2_mu_TPMU_PUBLIC_ID_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMI_ALG_PUBLIC type, -+ TPMU_PUBLIC_ID *p); ++ TPMI_ALG_PUBLIC type, ++ TPMU_PUBLIC_ID *p); + +void +grub_tpm2_mu_TPMT_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_PUBLIC *p); ++ TPMT_PUBLIC *p); + +void +grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf, -+ TPM2B_PUBLIC *p); ++ TPM2B_PUBLIC *p); + +void +grub_tpm2_mu_TPMS_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_NV_PUBLIC *p); ++ TPMS_NV_PUBLIC *p); + +void +grub_tpm2_mu_TPM2B_NV_PUBLIC_Unmarshal (grub_tpm2_buffer_t buf, -+ TPM2B_NV_PUBLIC *p); ++ TPM2B_NV_PUBLIC *p); + +void +grub_tpm2_mu_TPM2B_NAME_Unmarshal (grub_tpm2_buffer_t buf, -+ TPM2B_NAME *n); ++ TPM2B_NAME *n); + +void +grub_tpm2_mu_TPMS_TAGGED_PROPERTY_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_TAGGED_PROPERTY* property); ++ TPMS_TAGGED_PROPERTY* property); + +void +grub_tpm2_mu_TPMS_CAPABILITY_DATA_tpmProperties_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_CAPABILITY_DATA* capabilityData); ++ TPMS_CAPABILITY_DATA* capabilityData); + +void +grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMT_TK_CREATION *p); ++ TPMT_TK_CREATION *p); + +void +grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, -+ TPMS_PCR_SELECTION* pcrSelection); ++ TPMS_PCR_SELECTION* pcrSelection); + +void +grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, -+ TPML_PCR_SELECTION* pcrSelection); ++ TPML_PCR_SELECTION* pcrSelection); + +void +grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf, -+ TPML_DIGEST* digest); ++ TPML_DIGEST* digest); + +#endif /* ! GRUB_TPM2_MU_HEADER */ diff --git a/include/grub/tpm2/tcg2.h b/include/grub/tpm2/tcg2.h new file mode 100644 -index 0000000000..99f2fdd3b9 +index 000000000..553b3fd93 --- /dev/null +++ b/include/grub/tpm2/tcg2.h @@ -0,0 +1,34 @@ @@ -3469,17 +3521,17 @@ index 0000000000..99f2fdd3b9 + +grub_err_t +grub_tcg2_submit_command (grub_size_t input_size, -+ grub_uint8_t *input, -+ grub_size_t output_size, -+ grub_uint8_t *output); ++ grub_uint8_t *input, ++ grub_size_t output_size, ++ grub_uint8_t *output); + +#endif /* ! GRUB_TPM2_TCG2_HEADER */ diff --git a/include/grub/tpm2/tpm2.h b/include/grub/tpm2/tpm2.h new file mode 100644 -index 0000000000..4b7a9fbb57 +index 000000000..cfdc9edcd --- /dev/null +++ b/include/grub/tpm2/tpm2.h -@@ -0,0 +1,38 @@ +@@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation @@ -3505,19 +3557,15 @@ index 0000000000..4b7a9fbb57 +#include +#include + -+/* Defined in: TCG TPM Specification, v1.59, Part 2, Section 10.6.1. */ -+#define TPM2_PCR_TO_SELECT(x) ((x) / 8) -+#define TPM2_PCR_TO_BIT(x) (1 << ((x) % 8)) -+ +/* Well-Known Windows SRK handle */ +#define TPM2_SRK_HANDLE 0x81000001 + +typedef struct TPM2_SEALED_KEY { -+ TPM2B_PUBLIC public; -+ TPM2B_PRIVATE private; ++ TPM2B_PUBLIC public; ++ TPM2B_PRIVATE private; +} TPM2_SEALED_KEY; + +#endif /* ! GRUB_TPM2_TPM2_HEADER */ -- -2.34.1 +2.35.3 diff --git a/0005-tpm2-add-more-marshal-unmarshal-functions.patch b/0002-tpm2-Add-more-marshal-unmarshal-functions.patch similarity index 95% rename from 0005-tpm2-add-more-marshal-unmarshal-functions.patch rename to 0002-tpm2-Add-more-marshal-unmarshal-functions.patch index 6d8b6ce..ba87585 100644 --- a/0005-tpm2-add-more-marshal-unmarshal-functions.patch +++ b/0002-tpm2-Add-more-marshal-unmarshal-functions.patch @@ -1,7 +1,7 @@ -From ac5c47af318652a25df1788c73884e4e9b6e4ac1 Mon Sep 17 00:00:00 2001 +From 1d34522075949581ccb34a08dd73607566517824 Mon Sep 17 00:00:00 2001 From: Gary Lin Date: Tue, 7 Feb 2023 18:33:42 +0800 -Subject: [PATCH 05/13] tpm2: add more marshal/unmarshal functions +Subject: [PATCH 2/4] tpm2: Add more marshal/unmarshal functions Add a few more marshal/unmarshal functions to support authorized policy. @@ -34,7 +34,7 @@ Signed-off-by: Gary Lin 2 files changed, 337 insertions(+) diff --git a/grub-core/tpm2/mu.c b/grub-core/tpm2/mu.c -index 6d3294c5b..150a8d37d 100644 +index 1617f37cd..3a9a3c1be 100644 --- a/grub-core/tpm2/mu.c +++ b/grub-core/tpm2/mu.c @@ -383,6 +383,49 @@ grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, @@ -86,7 +86,7 @@ index 6d3294c5b..150a8d37d 100644 + void grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, - const TPM2B_SENSITIVE_CREATE *sensitiveCreate) + const TPM2B_SENSITIVE_CREATE *sensitiveCreate) @@ -405,6 +448,113 @@ grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, grub_tpm2_buffer_pack_u16 (buffer, 0); } @@ -200,7 +200,7 @@ index 6d3294c5b..150a8d37d 100644 + void grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buffer, - TPM2B* p) + TPM2B* p) @@ -775,6 +925,24 @@ grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buffer, grub_tpm2_mu_TPM2B_Unmarshal (buffer, (TPM2B*) &p->digest); } @@ -225,7 +225,7 @@ index 6d3294c5b..150a8d37d 100644 + void grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, - TPMS_PCR_SELECTION* pcrSelection) + TPMS_PCR_SELECTION* pcrSelection) @@ -805,3 +973,97 @@ grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf, for (grub_uint32_t i = 0; i < digest->count; i++) grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (buf, &digest->digests[i]); @@ -325,11 +325,11 @@ index 6d3294c5b..150a8d37d 100644 + grub_tpm2_mu_TPMU_SIGNATURE_Unmarshal (buffer, p->sigAlg, &p->signature); +} diff --git a/include/grub/tpm2/mu.h b/include/grub/tpm2/mu.h -index 1e5065bb4..158dbe188 100644 +index c545976db..afb842ab5 100644 --- a/include/grub/tpm2/mu.h +++ b/include/grub/tpm2/mu.h @@ -147,6 +147,47 @@ grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf, - const TPM2B_SENSITIVE_CREATE *sensitiveCreate); + const TPM2B_SENSITIVE_CREATE *sensitiveCreate); void +grub_tpm2_mu_TPMU_SENSITIVE_COMPOSITE_Marshal (grub_tpm2_buffer_t buf, @@ -374,11 +374,11 @@ index 1e5065bb4..158dbe188 100644 + const TPMT_TK_VERIFIED *p); +void grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buf, - TPM2B* p); + TPM2B* p); @@ -277,6 +318,14 @@ void grub_tpm2_mu_TPMT_TK_CREATION_Unmarshal (grub_tpm2_buffer_t buf, - TPMT_TK_CREATION *p); + TPMT_TK_CREATION *p); +void +grub_tpm2_mu_TPMT_TK_HASHCHECK_Unmarshal (grub_tpm2_buffer_t buf, @@ -390,10 +390,10 @@ index 1e5065bb4..158dbe188 100644 + void grub_tpm2_mu_TPMS_PCR_SELECTION_Unmarshal (grub_tpm2_buffer_t buf, - TPMS_PCR_SELECTION* pcrSelection); + TPMS_PCR_SELECTION* pcrSelection); @@ -289,4 +338,30 @@ void grub_tpm2_mu_TPML_DIGEST_Unmarshal (grub_tpm2_buffer_t buf, - TPML_DIGEST* digest); + TPML_DIGEST* digest); +void +grub_tpm2_mu_TPMS_SIGNATURE_RSA_Unmarshal (grub_tpm2_buffer_t buf, diff --git a/0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch b/0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch deleted file mode 100644 index cdf295b..0000000 --- a/0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch +++ /dev/null @@ -1,696 +0,0 @@ -From 2b94a992464aa2d00333ab3f13f065da99196440 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Tue, 7 Feb 2023 18:14:59 +0800 -Subject: [PATCH 02/13] tpm2: declare the input arguments of TPM2 functions as - const - -The arguments, except the buffer, of the marshal functions are invariable. -Also, the TPM2 command parameters are supposed not changed by the -command. Declare those arguments as 'const' so that the compiler can -help to detect the undesired change on those arguments. Besides, it's -easier to tell which arguments are the command parameters and which are -the response parameters. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/mu.c | 64 +++++++++++++------------- - grub-core/tpm2/tpm2.c | 64 +++++++++++++------------- - include/grub/tpm2/internal/functions.h | 64 +++++++++++++------------- - include/grub/tpm2/mu.h | 64 +++++++++++++------------- - 4 files changed, 128 insertions(+), 128 deletions(-) - -diff --git a/grub-core/tpm2/mu.c b/grub-core/tpm2/mu.c -index c5f5c7b5f..6d3294c5b 100644 ---- a/grub-core/tpm2/mu.c -+++ b/grub-core/tpm2/mu.c -@@ -49,7 +49,7 @@ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buffer, -- grub_uint16_t size, -+ const grub_uint16_t size, - const grub_uint8_t* b) - { - grub_tpm2_buffer_pack_u16 (buffer, size); -@@ -60,8 +60,8 @@ grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_SYM_OBJECT algorithm, -- TPMU_SYM_KEY_BITS *p) -+ const TPMI_ALG_SYM_OBJECT algorithm, -+ const TPMU_SYM_KEY_BITS *p) - { - switch (algorithm) - { -@@ -78,8 +78,8 @@ grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_SYM_OBJECT algorithm, -- TPMU_SYM_MODE *p) -+ const TPMI_ALG_SYM_OBJECT algorithm, -+ const TPMU_SYM_MODE *p) - { - switch (algorithm) - { -@@ -96,7 +96,7 @@ grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_SYM_DEF *p) -+ const TPMT_SYM_DEF *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->algorithm); - grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (buffer, p->algorithm, &p->keyBits); -@@ -134,7 +134,7 @@ grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_SCHEME_XOR *p) -+ const TPMS_SCHEME_XOR *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg); - grub_tpm2_buffer_pack_u16 (buffer, p->kdf); -@@ -142,15 +142,15 @@ grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_SCHEME_HMAC *p) -+ const TPMS_SCHEME_HMAC *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->hashAlg); - } - - void - grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_KEYEDHASH_SCHEME scheme, -- TPMU_SCHEME_KEYEDHASH *p) -+ const TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ const TPMU_SCHEME_KEYEDHASH *p) - { - switch (scheme) - { -@@ -170,7 +170,7 @@ grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_KEYEDHASH_SCHEME *p) -+ const TPMT_KEYEDHASH_SCHEME *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->scheme); - grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (buffer, p->scheme, &p->details); -@@ -178,14 +178,14 @@ grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_KEYEDHASH_PARMS *p) -+ const TPMS_KEYEDHASH_PARMS *p) - { - grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (buffer, &p->scheme); - } - - void - grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_SYM_DEF_OBJECT *p) -+ const TPMT_SYM_DEF_OBJECT *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->algorithm); - grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (buffer, p->algorithm, &p->keyBits); -@@ -194,8 +194,8 @@ grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_RSA_DECRYPT scheme, -- TPMU_ASYM_SCHEME *p __attribute__ ((unused))) -+ const TPMI_ALG_RSA_DECRYPT scheme, -+ const TPMU_ASYM_SCHEME *p __attribute__ ((unused))) - { - switch (scheme) - { -@@ -210,7 +210,7 @@ grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_RSA_SCHEME *p) -+ const TPMT_RSA_SCHEME *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->scheme); - grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (buffer, p->scheme, &p->details); -@@ -218,7 +218,7 @@ grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_RSA_PARMS *p) -+ const TPMS_RSA_PARMS *p) - { - grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->symmetric); - grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (buffer, &p->scheme); -@@ -228,14 +228,14 @@ grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_SYMCIPHER_PARMS *p) -+ const TPMS_SYMCIPHER_PARMS *p) - { - grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->sym); - } - - void - grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_ECC_SCHEME *p) -+ const TPMT_ECC_SCHEME *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->scheme); - grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (buffer, p->scheme, &p->details); -@@ -243,8 +243,8 @@ grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_KDF scheme, -- TPMU_KDF_SCHEME *p) -+ const TPMI_ALG_KDF scheme, -+ const TPMU_KDF_SCHEME *p) - { - switch (scheme) - { -@@ -270,7 +270,7 @@ grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_KDF_SCHEME *p) -+ const TPMT_KDF_SCHEME *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->scheme); - grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (buffer, p->scheme, &p->details); -@@ -278,7 +278,7 @@ grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_ECC_PARMS *p) -+ const TPMS_ECC_PARMS *p) - { - grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (buffer, &p->symmetric); - grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (buffer, &p->scheme); -@@ -288,8 +288,8 @@ grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer, -- grub_uint32_t type, -- TPMU_PUBLIC_PARMS *p) -+ const grub_uint32_t type, -+ const TPMU_PUBLIC_PARMS *p) - { - switch (type) - { -@@ -313,7 +313,7 @@ grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_ECC_POINT *p) -+ const TPMS_ECC_POINT *p) - { - grub_tpm2_mu_TPM2B_Marshal (buffer, p->x.size, p->x.buffer); - grub_tpm2_mu_TPM2B_Marshal (buffer, p->y.size, p->y.buffer); -@@ -321,8 +321,8 @@ grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buffer, -- TPMI_ALG_PUBLIC type, -- TPMU_PUBLIC_ID *p) -+ const TPMI_ALG_PUBLIC type, -+ const TPMU_PUBLIC_ID *p) - { - switch(type) - { -@@ -344,7 +344,7 @@ grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, -- TPMT_PUBLIC *p) -+ const TPMT_PUBLIC *p) - { - grub_tpm2_buffer_pack_u16 (buffer, p->type); - grub_tpm2_buffer_pack_u16 (buffer, p->nameAlg); -@@ -356,7 +356,7 @@ grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, -- TPM2B_PUBLIC *p) -+ const TPM2B_PUBLIC *p) - { - grub_uint32_t start; - grub_uint16_t size; -@@ -377,7 +377,7 @@ grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, -- TPMS_SENSITIVE_CREATE *p) -+ const TPMS_SENSITIVE_CREATE *p) - { - grub_tpm2_mu_TPM2B_Marshal (buffer, p->userAuth.size, p->userAuth.buffer); - grub_tpm2_mu_TPM2B_Marshal (buffer, p->data.size, p->data.buffer); -@@ -385,7 +385,7 @@ grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, - - void - grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buffer, -- TPM2B_SENSITIVE_CREATE *sensitiveCreate) -+ const TPM2B_SENSITIVE_CREATE *sensitiveCreate) - { - grub_uint32_t start; - grub_uint16_t size; -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 1cd969d5d..5377ad2c7 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -76,12 +76,12 @@ grub_tpm2_submit_command (TPMI_ST_COMMAND_TAG tag, - } - - TPM_RC --TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, -+TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_SENSITIVE_CREATE *inSensitive, -- TPM2B_PUBLIC *inPublic, -- TPM2B_DATA *outsideInfo, -- TPML_PCR_SELECTION *creationPCR, -+ const TPM2B_SENSITIVE_CREATE *inSensitive, -+ const TPM2B_PUBLIC *inPublic, -+ const TPM2B_DATA *outsideInfo, -+ const TPML_PCR_SELECTION *creationPCR, - TPM_HANDLE *objectHandle, - TPM2B_PUBLIC *outPublic, - TPM2B_CREATION_DATA *creationData, -@@ -165,14 +165,14 @@ TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, - } - - TPM_RC --TPM2_StartAuthSession (TPMI_DH_OBJECT tpmKey, -- TPMI_DH_ENTITY bind, -+TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, -+ const TPMI_DH_ENTITY bind, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_NONCE *nonceCaller, -- TPM2B_ENCRYPTED_SECRET *encryptedSalt, -- TPM_SE sessionType, -- TPMT_SYM_DEF *symmetric, -- TPMI_ALG_HASH authHash, -+ const TPM2B_NONCE *nonceCaller, -+ const TPM2B_ENCRYPTED_SECRET *encryptedSalt, -+ const TPM_SE sessionType, -+ const TPMT_SYM_DEF *symmetric, -+ const TPMI_ALG_HASH authHash, - TPMI_SH_AUTH_SESSION *sessionHandle, - TPM2B_NONCE *nonceTpm, - TPMS_AUTH_RESPONSE *authResponse) -@@ -235,10 +235,10 @@ TPM2_StartAuthSession (TPMI_DH_OBJECT tpmKey, - } - - TPM_RC --TPM2_PolicyPCR (TPMI_SH_POLICY policySessions, -+TPM2_PolicyPCR (const TPMI_SH_POLICY policySessions, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_DIGEST *pcrDigest, -- TPML_PCR_SELECTION *pcrs, -+ const TPM2B_DIGEST *pcrDigest, -+ const TPML_PCR_SELECTION *pcrs, - TPMS_AUTH_RESPONSE *authResponse) - { - TPM_RC rc; -@@ -285,7 +285,7 @@ TPM2_PolicyPCR (TPMI_SH_POLICY policySessions, - } - - TPM_RC --TPM2_ReadPublic (TPMI_DH_OBJECT objectHandle, -+TPM2_ReadPublic (const TPMI_DH_OBJECT objectHandle, - const TPMS_AUTH_COMMAND* authCommand, - TPM2B_PUBLIC *outPublic) - { -@@ -322,10 +322,10 @@ TPM2_ReadPublic (TPMI_DH_OBJECT objectHandle, - } - - TPM_RC --TPM2_Load (TPMI_DH_OBJECT parent_handle, -- TPMS_AUTH_COMMAND const *authCommand, -- TPM2B_PRIVATE *inPrivate, -- TPM2B_PUBLIC *inPublic, -+TPM2_Load (const TPMI_DH_OBJECT parent_handle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ const TPM2B_PRIVATE *inPrivate, -+ const TPM2B_PUBLIC *inPublic, - TPM_HANDLE *objectHandle, - TPM2B_NAME *name, - TPMS_AUTH_RESPONSE *authResponse) -@@ -383,7 +383,7 @@ TPM2_Load (TPMI_DH_OBJECT parent_handle, - } - - TPM_RC --TPM2_Unseal (TPMI_DH_OBJECT itemHandle, -+TPM2_Unseal (const TPMI_DH_OBJECT itemHandle, - const TPMS_AUTH_COMMAND *authCommand, - TPM2B_SENSITIVE_DATA *outData, - TPMS_AUTH_RESPONSE *authResponse) -@@ -434,7 +434,7 @@ TPM2_Unseal (TPMI_DH_OBJECT itemHandle, - } - - TPM_RC --TPM2_FlushContext (TPMI_DH_CONTEXT handle) -+TPM2_FlushContext (const TPMI_DH_CONTEXT handle) - { - TPM_RC rc; - struct grub_tpm2_buffer in; -@@ -465,7 +465,7 @@ TPM2_FlushContext (TPMI_DH_CONTEXT handle) - - TPM_RC - TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, -- TPML_PCR_SELECTION *pcrSelectionIn, -+ const TPML_PCR_SELECTION *pcrSelectionIn, - grub_uint32_t *pcrUpdateCounter, - TPML_PCR_SELECTION *pcrSelectionOut, - TPML_DIGEST *pcrValues, -@@ -524,7 +524,7 @@ TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, - } - - TPM_RC --TPM2_PolicyGetDigest (TPMI_SH_POLICY policySession, -+TPM2_PolicyGetDigest (const TPMI_SH_POLICY policySession, - const TPMS_AUTH_COMMAND *authCommand, - TPM2B_DIGEST *policyDigest, - TPMS_AUTH_RESPONSE *authResponse) -@@ -576,12 +576,12 @@ TPM2_PolicyGetDigest (TPMI_SH_POLICY policySession, - } - - TPM_RC --TPM2_Create (TPMI_DH_OBJECT parentHandle, -+TPM2_Create (const TPMI_DH_OBJECT parentHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_SENSITIVE_CREATE *inSensitive, -- TPM2B_PUBLIC *inPublic, -- TPM2B_DATA *outsideInfo, -- TPML_PCR_SELECTION *creationPCR, -+ const TPM2B_SENSITIVE_CREATE *inSensitive, -+ const TPM2B_PUBLIC *inPublic, -+ const TPM2B_DATA *outsideInfo, -+ const TPML_PCR_SELECTION *creationPCR, - TPM2B_PRIVATE *outPrivate, - TPM2B_PUBLIC *outPublic, - TPM2B_CREATION_DATA *creationData, -@@ -660,10 +660,10 @@ TPM2_Create (TPMI_DH_OBJECT parentHandle, - } - - TPM_RC --TPM2_EvictControl (TPMI_RH_PROVISION auth, -- TPMI_DH_OBJECT objectHandle, -+TPM2_EvictControl (const TPMI_RH_PROVISION auth, -+ const TPMI_DH_OBJECT objectHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPMI_DH_PERSISTENT persistentHandle, -+ const TPMI_DH_PERSISTENT persistentHandle, - TPMS_AUTH_RESPONSE *authResponse) - { - struct grub_tpm2_buffer in; -diff --git a/include/grub/tpm2/internal/functions.h b/include/grub/tpm2/internal/functions.h -index f08b45ed2..8fda8ceab 100644 ---- a/include/grub/tpm2/internal/functions.h -+++ b/include/grub/tpm2/internal/functions.h -@@ -22,12 +22,12 @@ - #include - - TPM_RC --TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, -+TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_SENSITIVE_CREATE *inSensitive, -- TPM2B_PUBLIC *inPublic, -- TPM2B_DATA *outsideInfo, -- TPML_PCR_SELECTION *creationPCR, -+ const TPM2B_SENSITIVE_CREATE *inSensitive, -+ const TPM2B_PUBLIC *inPublic, -+ const TPM2B_DATA *outsideInfo, -+ const TPML_PCR_SELECTION *creationPCR, - TPM_HANDLE *objectHandle, - TPM2B_PUBLIC *outPublic, - TPM2B_CREATION_DATA *creationData, -@@ -37,69 +37,69 @@ TPM2_CreatePrimary (TPMI_RH_HIERARCHY primaryHandle, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_StartAuthSession (TPMI_DH_OBJECT tpmKey, -- TPMI_DH_ENTITY bind, -+TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, -+ const TPMI_DH_ENTITY bind, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_NONCE *nonceCaller, -- TPM2B_ENCRYPTED_SECRET *encryptedSalt, -- TPM_SE sessionType, -- TPMT_SYM_DEF *symmetric, -- TPMI_ALG_HASH authHash, -+ const TPM2B_NONCE *nonceCaller, -+ const TPM2B_ENCRYPTED_SECRET *encryptedSalt, -+ const TPM_SE sessionType, -+ const TPMT_SYM_DEF *symmetric, -+ const TPMI_ALG_HASH authHash, - TPMI_SH_AUTH_SESSION *sessionHandle, - TPM2B_NONCE *nonceTpm, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_PolicyPCR (TPMI_SH_POLICY policySession, -+TPM2_PolicyPCR (const TPMI_SH_POLICY policySession, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_DIGEST *pcrDigest, -- TPML_PCR_SELECTION *pcrs, -+ const TPM2B_DIGEST *pcrDigest, -+ const TPML_PCR_SELECTION *pcrs, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_ReadPublic (TPMI_DH_OBJECT objectHandle, -+TPM2_ReadPublic (const TPMI_DH_OBJECT objectHandle, - const TPMS_AUTH_COMMAND* authCommand, - TPM2B_PUBLIC *outPublic); - - TPM_RC --TPM2_Load (TPMI_DH_OBJECT parent_handle, -- TPMS_AUTH_COMMAND const *authCommand, -- TPM2B_PRIVATE *inPrivate, -- TPM2B_PUBLIC *inPublic, -+TPM2_Load (const TPMI_DH_OBJECT parent_handle, -+ const TPMS_AUTH_COMMAND *authCommand, -+ const TPM2B_PRIVATE *inPrivate, -+ const TPM2B_PUBLIC *inPublic, - TPM_HANDLE *objectHandle, - TPM2B_NAME *name, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_Unseal (TPMI_DH_OBJECT item_handle, -+TPM2_Unseal (const TPMI_DH_OBJECT item_handle, - const TPMS_AUTH_COMMAND *authCommand, - TPM2B_SENSITIVE_DATA *outData, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_FlushContext (TPMI_DH_CONTEXT handle); -+TPM2_FlushContext (const TPMI_DH_CONTEXT handle); - - TPM_RC - TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, -- TPML_PCR_SELECTION *pcrSelectionIn, -+ const TPML_PCR_SELECTION *pcrSelectionIn, - grub_uint32_t *pcrUpdateCounter, - TPML_PCR_SELECTION *pcrSelectionOut, - TPML_DIGEST *pcrValues, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_PolicyGetDigest (TPMI_SH_POLICY policySession, -+TPM2_PolicyGetDigest (const TPMI_SH_POLICY policySession, - const TPMS_AUTH_COMMAND *authCommand, - TPM2B_DIGEST *policyDigest, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_Create (TPMI_DH_OBJECT parentHandle, -+TPM2_Create (const TPMI_DH_OBJECT parentHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPM2B_SENSITIVE_CREATE *inSensitive, -- TPM2B_PUBLIC *inPublic, -- TPM2B_DATA *outsideInfo, -- TPML_PCR_SELECTION *creationPCR, -+ const TPM2B_SENSITIVE_CREATE *inSensitive, -+ const TPM2B_PUBLIC *inPublic, -+ const TPM2B_DATA *outsideInfo, -+ const TPML_PCR_SELECTION *creationPCR, - TPM2B_PRIVATE *outPrivate, - TPM2B_PUBLIC *outPublic, - TPM2B_CREATION_DATA *creationData, -@@ -108,10 +108,10 @@ TPM2_Create (TPMI_DH_OBJECT parentHandle, - TPMS_AUTH_RESPONSE *authResponse); - - TPM_RC --TPM2_EvictControl (TPMI_RH_PROVISION auth, -- TPMI_DH_OBJECT objectHandle, -+TPM2_EvictControl (const TPMI_RH_PROVISION auth, -+ const TPMI_DH_OBJECT objectHandle, - const TPMS_AUTH_COMMAND *authCommand, -- TPMI_DH_PERSISTENT persistentHandle, -+ const TPMI_DH_PERSISTENT persistentHandle, - TPMS_AUTH_RESPONSE *authResponse); - - #endif /* ! GRUB_TPM2_INTERNAL_FUNCTIONS_HEADER */ -diff --git a/include/grub/tpm2/mu.h b/include/grub/tpm2/mu.h -index 4f4058f9d..1e5065bb4 100644 ---- a/include/grub/tpm2/mu.h -+++ b/include/grub/tpm2/mu.h -@@ -28,22 +28,22 @@ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (grub_tpm2_buffer_t buf, - - void - grub_tpm2_mu_TPM2B_Marshal (grub_tpm2_buffer_t buf, -- grub_uint16_t size, -+ const grub_uint16_t size, - const grub_uint8_t* buffer); - - void - grub_tpm2_mu_TPMU_SYM_KEY_BITS_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_SYM_OBJECT algorithm, -- TPMU_SYM_KEY_BITS *p); -+ const TPMI_ALG_SYM_OBJECT algorithm, -+ const TPMU_SYM_KEY_BITS *p); - - void - grub_tpm2_mu_TPMU_SYM_MODE_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_SYM_OBJECT algorithm, -- TPMU_SYM_MODE *p); -+ const TPMI_ALG_SYM_OBJECT algorithm, -+ const TPMU_SYM_MODE *p); - - void - grub_tpm2_mu_TPMT_SYM_DEF_Marshal (grub_tpm2_buffer_t buf, -- TPMT_SYM_DEF *p); -+ const TPMT_SYM_DEF *p); - - void - grub_tpm2_mu_TPMS_PCR_SELECTION_Marshal (grub_tpm2_buffer_t buf, -@@ -59,92 +59,92 @@ grub_tpm2_mu_TPMA_OBJECT_Marshal (grub_tpm2_buffer_t buf, - - void - grub_tpm2_mu_TPMS_SCHEME_XOR_Marshal (grub_tpm2_buffer_t buf, -- TPMS_SCHEME_XOR *p); -+ const TPMS_SCHEME_XOR *p); - - void - grub_tpm2_mu_TPMS_SCHEME_HMAC_Marshal (grub_tpm2_buffer_t buf, -- TPMS_SCHEME_HMAC *p); -+ const TPMS_SCHEME_HMAC *p); - - void - grub_tpm2_mu_TPMU_SCHEME_KEYEDHASH_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_KEYEDHASH_SCHEME scheme, -- TPMU_SCHEME_KEYEDHASH *p); -+ const TPMI_ALG_KEYEDHASH_SCHEME scheme, -+ const TPMU_SCHEME_KEYEDHASH *p); - - void - grub_tpm2_mu_TPMT_KEYEDHASH_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMT_KEYEDHASH_SCHEME *p); -+ const TPMT_KEYEDHASH_SCHEME *p); - - void - grub_tpm2_mu_TPMS_KEYEDHASH_PARMS_Marshal (grub_tpm2_buffer_t buf, -- TPMS_KEYEDHASH_PARMS *p); -+ const TPMS_KEYEDHASH_PARMS *p); - - void - grub_tpm2_mu_TPMT_SYM_DEF_OBJECT_Marshal (grub_tpm2_buffer_t buf, -- TPMT_SYM_DEF_OBJECT *p); -+ const TPMT_SYM_DEF_OBJECT *p); - - void - grub_tpm2_mu_TPMU_ASYM_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_RSA_DECRYPT scheme, -- TPMU_ASYM_SCHEME *p); -+ const TPMI_ALG_RSA_DECRYPT scheme, -+ const TPMU_ASYM_SCHEME *p); - - void - grub_tpm2_mu_TPMT_RSA_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMT_RSA_SCHEME *p); -+ const TPMT_RSA_SCHEME *p); - - void - grub_tpm2_mu_TPMS_RSA_PARMS_Marshal (grub_tpm2_buffer_t buf, -- TPMS_RSA_PARMS *p); -+ const TPMS_RSA_PARMS *p); - - void - grub_tpm2_mu_TPMS_SYMCIPHER_PARMS_Marshal (grub_tpm2_buffer_t buf, -- TPMS_SYMCIPHER_PARMS *p); -+ const TPMS_SYMCIPHER_PARMS *p); - - void - grub_tpm2_mu_TPMT_ECC_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMT_ECC_SCHEME *p); -+ const TPMT_ECC_SCHEME *p); - - void - grub_tpm2_mu_TPMU_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_KDF scheme, -- TPMU_KDF_SCHEME *p); -+ const TPMI_ALG_KDF scheme, -+ const TPMU_KDF_SCHEME *p); - - void - grub_tpm2_mu_TPMT_KDF_SCHEME_Marshal (grub_tpm2_buffer_t buf, -- TPMT_KDF_SCHEME *p); -+ const TPMT_KDF_SCHEME *p); - - void - grub_tpm2_mu_TPMS_ECC_PARMS_Marshal (grub_tpm2_buffer_t buf, -- TPMS_ECC_PARMS *p); -+ const TPMS_ECC_PARMS *p); - - void - grub_tpm2_mu_TPMU_PUBLIC_PARMS_Marshal (grub_tpm2_buffer_t buf, -- grub_uint32_t type, -- TPMU_PUBLIC_PARMS *p); -+ const grub_uint32_t type, -+ const TPMU_PUBLIC_PARMS *p); - - void - grub_tpm2_mu_TPMS_ECC_POINT_Marshal (grub_tpm2_buffer_t buf, -- TPMS_ECC_POINT *p); -+ const TPMS_ECC_POINT *p); - - void - grub_tpm2_mu_TPMU_PUBLIC_ID_Marshal (grub_tpm2_buffer_t buf, -- TPMI_ALG_PUBLIC type, -- TPMU_PUBLIC_ID *p); -+ const TPMI_ALG_PUBLIC type, -+ const TPMU_PUBLIC_ID *p); - - void - grub_tpm2_mu_TPMT_PUBLIC_Marshal (grub_tpm2_buffer_t buf, -- TPMT_PUBLIC *p); -+ const TPMT_PUBLIC *p); - - void - grub_tpm2_mu_TPM2B_PUBLIC_Marshal (grub_tpm2_buffer_t buf, -- TPM2B_PUBLIC *p); -+ const TPM2B_PUBLIC *p); - - void - grub_tpm2_mu_TPMS_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf, -- TPMS_SENSITIVE_CREATE *p); -+ const TPMS_SENSITIVE_CREATE *p); - - void - grub_tpm2_mu_TPM2B_SENSITIVE_CREATE_Marshal (grub_tpm2_buffer_t buf, -- TPM2B_SENSITIVE_CREATE *sensitiveCreate); -+ const TPM2B_SENSITIVE_CREATE *sensitiveCreate); - - void - grub_tpm2_mu_TPM2B_Unmarshal (grub_tpm2_buffer_t buf, --- -2.35.3 - diff --git a/0003-protectors-Add-TPM2-Key-Protector.patch b/0003-protectors-Add-TPM2-Key-Protector.patch new file mode 100644 index 0000000..026ea93 --- /dev/null +++ b/0003-protectors-Add-TPM2-Key-Protector.patch @@ -0,0 +1,2002 @@ +From ab730e5bc42bae528da62178680284efdd64278e Mon Sep 17 00:00:00 2001 +From: Hernan Gatta +Date: Tue, 1 Feb 2022 05:02:55 -0800 +Subject: [PATCH 3/5] protectors: Add TPM2 Key Protector + +The TPM2 key protector is a module that enables the automatic retrieval +of a fully-encrypted disk's unlocking key from a TPM 2.0. + +The theory of operation is such that the module accepts various +arguments, most of which are optional and therefore possess reasonable +defaults. One of these arguments is the keyfile/tpm2key parameter, which +is mandatory. There are two supported key formats: + +1. Raw Sealed Key (--keyfile) + When sealing a key with TPM2_Create, the public portion of the sealed + key is stored in TPM2B_PUBLIC, and the private portion is in + TPM2B_PRIVATE. The raw sealed key glues the fully marshalled + TPM2B_PUBLIC and TPM2B_PRIVATE into one file. + +2. TPM 2.0 Key (--tpm2key) + The following is the ASN.1 definition of TPM 2.0 Key File: + + TPMPolicy ::= SEQUENCE { + CommandCode [0] EXPLICIT INTEGER + CommandPolicy [1] EXPLICIT OCTET STRING + } + + TPMAuthPolicy ::= SEQUENCE { + Name [0] EXPLICIT UTF8STRING OPTIONAL + Policy [1] EXPLICIT SEQUENCE OF TPMPolicy + } + + TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL + policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL + secret [2] EXPLICIT OCTET STRING OPTIONAL + authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL + parent INTEGER + pubkey OCTET STRING + privkey OCTET STRING + } + + The TPM2 key protector only expects a "sealed" key in DER encoding, + so 'type' is always 2.23.133.10.1.5, 'emptyAuth' is 'TRUE', and + 'secret' is empty. 'policy' and 'authPolicy' are the possible policy + command sequences to construst the policy digest to unseal the key. + Similar to the raw sealed key, the public portion (TPM2B_PUBLIC) of + the sealed key is stored in 'pubkey', and the private portion + (TPM2B_PRIVATE) is in 'privkey'. + + For more details: https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html + +This sealed key file is created via the grub-protect tool. The tool +utilizes the TPM's sealing functionality to seal (i.e., encrypt) an +unlocking key using a Storage Root Key (SRK) to the values of various +Platform Configuration Registers (PCRs). These PCRs reflect the state +of the system as it boots. If the values are as expected, the system +may be considered trustworthy, at which point the TPM allows for a +caller to utilize the private component of the SRK to unseal (i.e., +decrypt) the sealed key file. The caller, in this case, is this key +protector. + +The TPM2 key protector registers two commands: + +- tpm2_key_protector_init: Initializes the state of the TPM2 key + protector for later usage, clearing any + previous state, too, if any. + +- tpm2_key_protector_clear: Clears any state set by tpm2_key_protector_init. + +The way this is expected to be used requires the user to, either +interactively or, normally, via a boot script, initialize/configure +the key protector and then specify that it be used by the 'cryptomount' +command (modifications to this command are in a different patch). + +For instance, to unseal the raw sealed key file: + +tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub2/sealed-1.key +cryptomount DISK1 -P tpm2 + +tpm2_key_protector_init --keyfile=(hd0,gpt1)/efi/grub2/sealed-2.key --pcrs=7,11 +cryptomount DISK2 -P tpm2 + +Or, to unseal the TPM 2.0 Key file: + +tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub2/sealed-1.tpm +cryptomount DISK1 -P tpm2 + +tpm2_key_protector_init --tpm2key=(hd0,gpt1)/efi/grub2/sealed-2.tpm --pcrs=7,11 +cryptomount DISK2 -P tpm2 + +If a user does not initialize the key protector and attempts to use it +anyway, the protector returns an error. + +Before unsealing the key, the TPM2 key protector follows the "TPMPolicy" +sequences to enforce the TPM policy commands to construct a valid policy +digest to unseal the key. + +For the TPM 2.0 Key files, 'authPolicy' may contain multiple "TPMPolicy" +sequences, the TPM2 key protector iterates 'authPolicy' to find a valid +sequence to unseal key. If 'authPolicy' is empty or all sequences in +'authPolicy' fail, the protector tries the one from 'policy'. In case +'policy' is also empty, the protector creates a "TPMPolicy" sequence +based on the given PCR selection. + +For the raw sealed key, the TPM2 key protector treats the key file as a +TPM 2.0 Key file without 'authPolicy' and 'policy', so the "TPMPolicy" +sequence is always based on the PCR selection from the command +parameters. + +Currently, there is only one supported policy command: TPM2_PolicyPCR. +The command set can be extended to support advanced features, such as +as authorized policy, in the future. + +Signed-off-by: Hernan Gatta +Signed-off-by: Gary Lin +--- + grub-core/Makefile.core.def | 13 + + grub-core/tpm2/args.c | 131 ++++ + grub-core/tpm2/module.c | 1033 +++++++++++++++++++++++++++++ + grub-core/tpm2/tpm2key.asn | 31 + + grub-core/tpm2/tpm2key.c | 440 ++++++++++++ + grub-core/tpm2/tpm2key_asn1_tab.c | 41 ++ + include/grub/tpm2/internal/args.h | 39 ++ + include/grub/tpm2/tpm2key.h | 83 +++ + 8 files changed, 1811 insertions(+) + create mode 100644 grub-core/tpm2/args.c + create mode 100644 grub-core/tpm2/module.c + create mode 100644 grub-core/tpm2/tpm2key.asn + create mode 100644 grub-core/tpm2/tpm2key.c + create mode 100644 grub-core/tpm2/tpm2key_asn1_tab.c + create mode 100644 include/grub/tpm2/internal/args.h + create mode 100644 include/grub/tpm2/tpm2key.h + +diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def +index 0335d9add..4a8ff26a8 100644 +--- a/grub-core/Makefile.core.def ++++ b/grub-core/Makefile.core.def +@@ -2525,6 +2525,19 @@ module = { + enable = efi; + }; + ++module = { ++ name = tpm2; ++ common = tpm2/args.c; ++ common = tpm2/buffer.c; ++ common = tpm2/module.c; ++ common = tpm2/mu.c; ++ common = tpm2/tpm2.c; ++ common = tpm2/tpm2key.c; ++ common = tpm2/tpm2key_asn1_tab.c; ++ efi = tpm2/tcg2.c; ++ enable = efi; ++}; ++ + module = { + name = tr; + common = commands/tr.c; +diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c +new file mode 100644 +index 000000000..0113f64a8 +--- /dev/null ++++ b/grub-core/tpm2/args.c +@@ -0,0 +1,131 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Microsoft Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++grub_err_t ++grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, ++ grub_uint8_t *pcr_count) ++{ ++ char *current_pcr = value; ++ char *next_pcr; ++ unsigned long pcr; ++ grub_uint8_t i; ++ ++ if (grub_strlen (value) == 0) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ *pcr_count = 0; ++ for (i = 0; i < TPM_MAX_PCRS; i++) ++ { ++ next_pcr = grub_strchr (current_pcr, ','); ++ if (next_pcr == current_pcr) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Empty entry in PCR list")); ++ if (next_pcr) ++ *next_pcr = '\0'; ++ ++ grub_errno = GRUB_ERR_NONE; ++ pcr = grub_strtoul (current_pcr, NULL, 10); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_error (grub_errno, ++ N_("Entry '%s' in PCR list is not a number"), ++ current_pcr); ++ ++ if (pcr > TPM_MAX_PCRS) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Entry %lu in PCR list is too large to be a PCR " ++ "number, PCR numbers range from 0 to %u"), ++ pcr, TPM_MAX_PCRS); ++ ++ pcrs[i] = (grub_uint8_t)pcr; ++ *pcr_count += 1; ++ ++ if (next_pcr == NULL) ++ break; ++ ++ current_pcr = next_pcr + 1; ++ if (*current_pcr == '\0') ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Trailing comma at the end of PCR list")); ++ } ++ ++ if (i == TPM_MAX_PCRS) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Too many PCRs in PCR list, the maximum number of " ++ "PCRs is %u"), TPM_MAX_PCRS); ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm2_protector_parse_asymmetric (const char *value, TPM_ALG_ID *asymmetric) ++{ ++ if (grub_strcasecmp (value, "ECC") == 0) ++ *asymmetric = TPM_ALG_ECC; ++ else if (grub_strcasecmp (value, "RSA") == 0) ++ *asymmetric = TPM_ALG_RSA; ++ else ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Value '%s' is not a valid asymmetric key type"), ++ value); ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank) ++{ ++ if (grub_strcasecmp (value, "SHA1") == 0) ++ *bank = TPM_ALG_SHA1; ++ else if (grub_strcasecmp (value, "SHA256") == 0) ++ *bank = TPM_ALG_SHA256; ++ else if (grub_strcasecmp (value, "SHA384") == 0) ++ *bank = TPM_ALG_SHA384; ++ else if (grub_strcasecmp (value, "SHA512") == 0) ++ *bank = TPM_ALG_SHA512; ++ else ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Value '%s' is not a valid PCR bank"), value); ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle) ++{ ++ unsigned long num; ++ ++ grub_errno = GRUB_ERR_NONE; ++ num = grub_strtoul (value, NULL, 0); ++ if (grub_errno != GRUB_ERR_NONE) ++ return grub_error (grub_errno, N_("TPM handle value '%s' is not a number"), ++ value); ++ ++ if (num > GRUB_UINT_MAX) ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Value %lu is too large to be a TPM handle, TPM " ++ "handles are unsigned 32-bit integers"), num); ++ ++ *handle = (TPM_HANDLE)num; ++ ++ return GRUB_ERR_NONE; ++} +diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c +new file mode 100644 +index 000000000..5274296b7 +--- /dev/null ++++ b/grub-core/tpm2/module.c +@@ -0,0 +1,1033 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Microsoft Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++GRUB_MOD_LICENSE ("GPLv3+"); ++ ++typedef enum grub_tpm2_protector_mode ++{ ++ GRUB_TPM2_PROTECTOR_MODE_UNSET, ++ GRUB_TPM2_PROTECTOR_MODE_SRK, ++ GRUB_TPM2_PROTECTOR_MODE_NV ++} grub_tpm2_protector_mode_t; ++ ++enum grub_tpm2_protector_options ++{ ++ OPTION_MODE, ++ OPTION_PCRS, ++ OPTION_BANK, ++ OPTION_TPM2KEY, ++ OPTION_KEYFILE, ++ OPTION_SRK, ++ OPTION_ASYMMETRIC, ++ OPTION_NVINDEX ++}; ++ ++struct grub_tpm2_protector_context ++{ ++ grub_tpm2_protector_mode_t mode; ++ grub_uint8_t pcrs[TPM_MAX_PCRS]; ++ grub_uint8_t pcr_count; ++ TPM_ALG_ID asymmetric; ++ TPM_ALG_ID bank; ++ const char *tpm2key; ++ const char *keyfile; ++ TPM_HANDLE srk; ++ TPM_HANDLE nv; ++}; ++ ++static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = ++ { ++ /* Options for all modes */ ++ { ++ .longarg = "mode", ++ .shortarg = 'm', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV " ++ "Index ('nv')."), ++ }, ++ { ++ .longarg = "pcrs", ++ .shortarg = 'p', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Comma-separated list of PCRs used to authorize key release " ++ "(e.g., '7,11', default is 7."), ++ }, ++ { ++ .longarg = "bank", ++ .shortarg = 'b', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Bank of PCRs used to authorize key release: " ++ "SHA1, SHA256 (default), or SHA384."), ++ }, ++ /* SRK-mode options */ ++ { ++ .longarg = "tpm2key", ++ .shortarg = 'T', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Required in SRK mode, path to the key file in TPM 2.0 Key File Format " ++ "to unseal using the TPM (e.g., (hd0,gpt1)/boot/grub2/secret.tpm)."), ++ }, ++ { ++ .longarg = "keyfile", ++ .shortarg = 'k', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Required in SRK mode, path to the sealed key file to unseal using " ++ "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key). " ++ "Use '-tpm2key' instead"), ++ }, ++ { ++ .longarg = "srk", ++ .shortarg = 's', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("In SRK mode, the SRK handle if the SRK is persistent " ++ "(default is 0x81000001)."), ++ }, ++ { ++ .longarg = "asymmetric", ++ .shortarg = 'a', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("In SRK mode, the type of SRK: RSA (default) or ECC."), ++ }, ++ /* NV Index-mode options */ ++ { ++ .longarg = "nvindex", ++ .shortarg = 'n', ++ .flags = 0, ++ .arg = NULL, ++ .type = ARG_TYPE_STRING, ++ .doc = ++ N_("Required in NV Index mode, the NV handle to read which must " ++ "readily exist on the TPM and which contains the key."), ++ }, ++ /* End of list */ ++ {0, 0, 0, 0, 0, 0} ++ }; ++ ++static grub_extcmd_t grub_tpm2_protector_init_cmd; ++static grub_extcmd_t grub_tpm2_protector_clear_cmd; ++static struct grub_tpm2_protector_context grub_tpm2_protector_ctx = { 0 }; ++ ++static grub_err_t ++grub_tpm2_protector_srk_read_file (const char *filepath, void **buffer, ++ grub_size_t *buffer_size) ++{ ++ grub_file_t file; ++ grub_off_t file_size; ++ void *read_buffer; ++ grub_off_t read_n; ++ ++ /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9 ++ * otherwise we'll never be able to predict the value of PCR9 at unseal time */ ++ file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); ++ if (file == NULL) ++ { ++ grub_dprintf ("tpm2", "Could not open file: %s\n", filepath); ++ /* grub_file_open sets grub_errno on error, and if we do no unset it, ++ * future calls to grub_file_open will fail (and so will anybody up the ++ * stack who checks the value, if any). */ ++ grub_errno = GRUB_ERR_NONE; ++ return GRUB_ERR_FILE_NOT_FOUND; ++ } ++ ++ file_size = grub_file_size (file); ++ if (file_size == 0) ++ { ++ grub_dprintf ("tpm2", "Could not read file size: %s\n", filepath); ++ grub_file_close (file); ++ return GRUB_ERR_OUT_OF_RANGE; ++ } ++ ++ read_buffer = grub_malloc (file_size); ++ if (read_buffer == NULL) ++ { ++ grub_dprintf ("tpm2", "Could not allocate buffer for %s.\n", filepath); ++ grub_file_close (file); ++ return GRUB_ERR_OUT_OF_MEMORY; ++ } ++ ++ read_n = grub_file_read (file, read_buffer, file_size); ++ if (read_n != file_size) ++ { ++ grub_dprintf ("tpm2", "Could not retrieve file contents: %s\n", filepath); ++ grub_free (read_buffer); ++ grub_file_close (file); ++ return GRUB_ERR_FILE_READ_ERROR; ++ } ++ ++ grub_file_close (file); ++ ++ *buffer = read_buffer; ++ *buffer_size = file_size; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_srk_unmarshal_keyfile (void *sealed_key, ++ grub_size_t sealed_key_size, ++ TPM2_SEALED_KEY *sk) ++{ ++ struct grub_tpm2_buffer buf; ++ ++ grub_tpm2_buffer_init (&buf); ++ if (sealed_key_size > buf.cap) ++ { ++ grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer " ++ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", ++ sealed_key_size, buf.cap); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } ++ ++ grub_memcpy (buf.data, sealed_key, sealed_key_size); ++ buf.size = sealed_key_size; ++ ++ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); ++ grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private); ++ ++ if (buf.error) ++ { ++ grub_dprintf ("tpm2", "Could not unmarshal sealed key file, it is likely " ++ "malformed.\n"); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_srk_unmarshal_tpm2key (void *sealed_key, ++ grub_size_t sealed_key_size, ++ tpm2key_policy_t *policy_seq, ++ tpm2key_authpolicy_t *authpol_seq, ++ grub_uint32_t *parent, ++ TPM2_SEALED_KEY *sk) ++{ ++ asn1_node tpm2key = NULL; ++ grub_uint32_t parent_tmp; ++ void *sealed_pub = NULL; ++ grub_size_t sealed_pub_size; ++ void *sealed_priv = NULL; ++ grub_size_t sealed_priv_size; ++ struct grub_tpm2_buffer buf; ++ grub_err_t err; ++ ++ /* ++ * Start to parse the tpm2key file ++ * TPMKey ::= SEQUENCE { ++ * type OBJECT IDENTIFIER, ++ * emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, ++ * policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, ++ * secret [2] EXPLICIT OCTET STRING OPTIONAL, ++ * authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, ++ * parent INTEGER, ++ * pubkey OCTET STRING, ++ * privkey OCTET STRING ++ * } ++ */ ++ err = grub_tpm2key_start_parsing (&tpm2key, sealed_key, sealed_key_size); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ ++ /* ++ * Retrieve the policy sequence from 'policy' ++ * policy_seq will be NULL when 'policy' is not available ++ */ ++ err = grub_tpm2key_get_policy_seq (tpm2key, policy_seq); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ ++ /* ++ * Retrieve the authpolicy sequence from 'authPolicy' ++ * authpol_seq will be NULL when 'authPolicy' is not available ++ */ ++ err = grub_tpm2key_get_authpolicy_seq (tpm2key, authpol_seq); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ ++ /* Retrieve the parent handle */ ++ err = grub_tpm2key_get_parent (tpm2key, &parent_tmp); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ *parent = parent_tmp; ++ ++ /* Retrieve the public part of the sealed key */ ++ err = grub_tpm2key_get_pubkey (tpm2key, &sealed_pub, &sealed_pub_size); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ ++ /* Retrieve the private part of the sealed key */ ++ err = grub_tpm2key_get_privkey (tpm2key, &sealed_priv, &sealed_priv_size); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ ++ /* Unmarshal the sealed key */ ++ grub_tpm2_buffer_init (&buf); ++ if (sealed_pub_size + sealed_priv_size > buf.cap) ++ { ++ grub_dprintf ("tpm2", "Sealed key is larger than decode buffer " ++ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", ++ sealed_pub_size, buf.cap); ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ grub_tpm2_buffer_pack (&buf, sealed_pub, sealed_pub_size); ++ grub_tpm2_buffer_pack (&buf, sealed_priv, sealed_priv_size); ++ ++ buf.offset = 0; ++ ++ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); ++ grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private); ++ ++ if (buf.error) ++ { ++ grub_dprintf ("tpm2", "Could not unmarshal sealed key, it is likely " ++ "malformed.\n"); ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ err = GRUB_ERR_NONE; ++ ++error: ++ /* End the parsing */ ++ grub_tpm2key_end_parsing (tpm2key); ++ grub_free (sealed_pub); ++ grub_free (sealed_priv); ++ ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_srk_get (const struct grub_tpm2_protector_context *ctx, ++ TPM_HANDLE parent, TPM_HANDLE *srk) ++{ ++ TPM_RC rc; ++ TPM2B_PUBLIC public; ++ TPMS_AUTH_COMMAND authCommand = { 0 }; ++ TPM2B_SENSITIVE_CREATE inSensitive = { 0 }; ++ TPM2B_PUBLIC inPublic = { 0 }; ++ TPM2B_DATA outsideInfo = { 0 }; ++ TPML_PCR_SELECTION creationPcr = { 0 }; ++ TPM2B_PUBLIC outPublic = { 0 }; ++ TPM2B_CREATION_DATA creationData = { 0 }; ++ TPM2B_DIGEST creationHash = { 0 }; ++ TPMT_TK_CREATION creationTicket = { 0 }; ++ TPM2B_NAME srkName = { 0 }; ++ TPM_HANDLE srkHandle; ++ ++ /* Find SRK */ ++ rc = TPM2_ReadPublic (ctx->srk, NULL, &public); ++ if (rc == TPM_RC_SUCCESS) ++ { ++ *srk = ctx->srk; ++ return GRUB_ERR_NONE; ++ } ++ ++ /* The handle exists but its public area could not be read. */ ++ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) ++ { ++ grub_dprintf ("tpm2", "The SRK handle (0x%x) exists on the TPM but its " ++ "public area could not be read (TPM2_ReadPublic " ++ "failed with TSS/TPM error %u).\n", ctx->srk, rc); ++ return GRUB_ERR_BAD_DEVICE; ++ } ++ ++ /* Create SRK */ ++ authCommand.sessionHandle = TPM_RS_PW; ++ inPublic.publicArea.type = ctx->asymmetric; ++ inPublic.publicArea.nameAlg = TPM_ALG_SHA256; ++ inPublic.publicArea.objectAttributes.restricted = 1; ++ inPublic.publicArea.objectAttributes.userWithAuth = 1; ++ inPublic.publicArea.objectAttributes.decrypt = 1; ++ inPublic.publicArea.objectAttributes.fixedTPM = 1; ++ inPublic.publicArea.objectAttributes.fixedParent = 1; ++ inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; ++ inPublic.publicArea.objectAttributes.noDA = 1; ++ ++ if (ctx->asymmetric == TPM_ALG_RSA) ++ { ++ inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES; ++ inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; ++ inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB; ++ inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; ++ inPublic.publicArea.parameters.rsaDetail.keyBits = 2048; ++ inPublic.publicArea.parameters.rsaDetail.exponent = 0; ++ } ++ else if (ctx->asymmetric == TPM_ALG_ECC) ++ { ++ inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES; ++ inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; ++ inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB; ++ inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; ++ inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256; ++ inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; ++ } ++ else ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ rc = TPM2_CreatePrimary (parent, &authCommand, &inSensitive, &inPublic, ++ &outsideInfo, &creationPcr, &srkHandle, &outPublic, ++ &creationData, &creationHash, &creationTicket, ++ &srkName, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ return grub_error (GRUB_ERR_BAD_DEVICE, ++ N_("Could not create SRK (TPM2_CreatePrimary: 0x%x)"), ++ rc); ++ ++ *srk = srkHandle; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session, ++ struct grub_tpm2_buffer *cmd_buf) ++{ ++ TPM2B_DIGEST pcr_digest; ++ TPML_PCR_SELECTION pcr_sel; ++ TPM_RC rc; ++ ++ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, &pcr_digest); ++ grub_tpm2_mu_TPML_PCR_SELECTION_Unmarshal (cmd_buf, &pcr_sel); ++ if (cmd_buf->error) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Failed to unmarshal CommandPolicy for TPM2_PolicyPCR")); ++ ++ rc = TPM2_PolicyPCR (session, NULL, &pcr_digest, &pcr_sel, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ return grub_error (GRUB_ERR_BAD_DEVICE, ++ N_("Failed to submit PCR policy (TPM2_PolicyPCR: 0x%x)"), ++ rc); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION session) ++{ ++ struct grub_tpm2_buffer buf; ++ grub_err_t err; ++ ++ grub_tpm2_buffer_init (&buf); ++ if (policy->cmd_policy_len > buf.cap) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("CommandPolicy larger than TPM buffer")); ++ ++ grub_memcpy (buf.data, policy->cmd_policy, policy->cmd_policy_len); ++ buf.size = policy->cmd_policy_len; ++ ++ switch (policy->cmd_code) ++ { ++ case TPM_CC_PolicyPCR: ++ err = grub_tpm2_protector_policypcr (session, &buf); ++ break; ++ default: ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("Unknown TPM Command: 0x%x"), policy->cmd_code); ++ } ++ ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_enforce_policy_seq (tpm2key_policy_t policy_seq, ++ TPMI_SH_AUTH_SESSION session) ++{ ++ tpm2key_policy_t policy; ++ grub_err_t err; ++ ++ FOR_LIST_ELEMENTS (policy, policy_seq) ++ { ++ err = grub_tpm2_protector_enforce_policy (policy, session); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_simple_policy_seq (const struct grub_tpm2_protector_context *ctx, ++ tpm2key_policy_t *policy_seq) ++{ ++ tpm2key_policy_t policy = NULL; ++ struct grub_tpm2_buffer buf; ++ TPML_PCR_SELECTION pcr_sel = { ++ .count = 1, ++ .pcrSelections = { ++ { ++ .hash = ctx->bank, ++ .sizeOfSelect = 3, ++ .pcrSelect = { 0 } ++ }, ++ } ++ }; ++ grub_uint8_t i; ++ grub_err_t err; ++ ++ if (policy_seq == NULL) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ grub_tpm2_buffer_init (&buf); ++ ++ for (i = 0; i < ctx->pcr_count; i++) ++ TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], ctx->pcrs[i]); ++ ++ grub_tpm2_buffer_pack_u16 (&buf, 0); ++ grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&buf, &pcr_sel); ++ ++ if (buf.error) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ policy = grub_malloc (sizeof(struct tpm2key_policy)); ++ if (policy == NULL) ++ { ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ goto error; ++ } ++ policy->cmd_code = TPM_CC_PolicyPCR; ++ policy->cmd_policy = grub_malloc (buf.size); ++ if (policy->cmd_policy == NULL) ++ { ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ goto error; ++ } ++ grub_memcpy (policy->cmd_policy, buf.data, buf.size); ++ policy->cmd_policy_len = buf.size; ++ ++ grub_list_push (GRUB_AS_LIST_P (policy_seq), GRUB_AS_LIST (policy)); ++ ++ return GRUB_ERR_NONE; ++ ++error: ++ grub_free (policy); ++ ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE sealed_handle, ++ grub_uint8_t **key, grub_size_t *key_size) ++{ ++ TPMS_AUTH_COMMAND authCmd = { 0 }; ++ TPM2B_SENSITIVE_DATA data; ++ TPM2B_NONCE nonceCaller = { 0 }; ++ TPMT_SYM_DEF symmetric = { 0 }; ++ TPMI_SH_AUTH_SESSION session; ++ grub_uint8_t *key_out; ++ TPM_RC rc; ++ grub_err_t err; ++ ++ /* Start Auth Session */ ++ nonceCaller.size = TPM_SHA256_DIGEST_SIZE; ++ symmetric.algorithm = TPM_ALG_NULL; ++ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonceCaller, NULL, ++ TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, ++ &session, NULL, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ return grub_error (GRUB_ERR_BAD_DEVICE, ++ N_("Failed to start auth session (TPM2_StartAuthSession: " ++ "0x%x)"), rc); ++ ++ /* Enforce the policy command sequence */ ++ err = grub_tpm2_protector_enforce_policy_seq (policy_seq, session); ++ if (err != GRUB_ERR_NONE) ++ goto error; ++ ++ /* Unseal Sealed Key */ ++ authCmd.sessionHandle = session; ++ rc = TPM2_Unseal (sealed_handle, &authCmd, &data, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal: 0x%x)"), ++ rc); ++ goto error; ++ } ++ ++ /* Epilogue */ ++ key_out = grub_malloc (data.size); ++ if (key_out == NULL) ++ { ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ grub_error (err, N_("No memory left to allocate unlock key buffer")); ++ goto error; ++ } ++ ++ grub_memcpy (key_out, data.buffer, data.size); ++ ++ *key = key_out; ++ *key_size = data.size; ++ ++ err = GRUB_ERR_NONE; ++ ++error: ++ TPM2_FlushContext (session); ++ ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, ++ grub_uint8_t **key, grub_size_t *key_size) ++{ ++ TPMS_AUTH_COMMAND authCmd = { 0 }; ++ TPM2_SEALED_KEY sealed_key = { 0 }; ++ TPM2B_NAME name = { 0 }; ++ void *file_bytes = NULL; ++ grub_size_t file_size = 0; ++ TPM_HANDLE parent_handle = 0; ++ TPM_HANDLE srk_handle = 0; ++ TPM_HANDLE sealed_handle = 0; ++ tpm2key_policy_t policy_seq = NULL; ++ tpm2key_authpolicy_t authpol = NULL; ++ tpm2key_authpolicy_t authpol_seq = NULL; ++ TPM_RC rc; ++ grub_err_t err; ++ ++ /* ++ * Retrieve sealed key, parent handle, policy sequence, and authpolicy ++ * sequence from the key file ++ */ ++ if (ctx->tpm2key) ++ { ++ err = grub_tpm2_protector_srk_read_file (ctx->tpm2key, &file_bytes, ++ &file_size); ++ if (err != GRUB_ERR_NONE) ++ return grub_error (err, N_("Failed to read key file %s"), ctx->tpm2key); ++ ++ err = grub_tpm2_protector_srk_unmarshal_tpm2key (file_bytes, ++ file_size, ++ &policy_seq, ++ &authpol_seq, ++ &parent_handle, ++ &sealed_key); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " ++ "TPM 2.0 Key File format")); ++ goto exit1; ++ } ++ } ++ else ++ { ++ err = grub_tpm2_protector_srk_read_file (ctx->keyfile, &file_bytes, ++ &file_size); ++ if (err != GRUB_ERR_NONE) ++ return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile); ++ ++ parent_handle = TPM_RH_OWNER; ++ err = grub_tpm2_protector_srk_unmarshal_keyfile (file_bytes, ++ file_size, ++ &sealed_key); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " ++ "TPM wire format")); ++ goto exit1; ++ } ++ } ++ ++ /* Get the SRK to unseal the sealed key */ ++ err = grub_tpm2_protector_srk_get (ctx, parent_handle, &srk_handle); ++ if (err != GRUB_ERR_NONE) ++ { ++ grub_error (err, N_("Failed to retrieve the SRK")); ++ goto exit1; ++ } ++ ++ /* Load the sealed key and associate it with the SRK */ ++ authCmd.sessionHandle = TPM_RS_PW; ++ rc = TPM2_Load (srk_handle, &authCmd, &sealed_key.private, &sealed_key.public, ++ &sealed_handle, &name, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to load sealed key (TPM2_Load: 0x%x)"), rc); ++ goto exit2; ++ } ++ ++ err = GRUB_ERR_READ_ERROR; ++ ++ /* Iterate the authpolicy sequence to find one that unseals the key */ ++ FOR_LIST_ELEMENTS (authpol, authpol_seq) ++ { ++ err = grub_tpm2_protector_unseal (authpol->policy_seq, sealed_handle, ++ key, key_size); ++ if (err == GRUB_ERR_NONE) ++ break; ++ ++ /* ++ * Push the error message into the grub_error stack ++ * Note: The grub_error stack may overflow if there are too many policy ++ * sequences. Anyway, we still can keep the error messages from ++ * the first few policy sequences which are usually most likely to ++ * unseal the key. ++ */ ++ grub_error_push(); ++ } ++ ++ /* Give the standalone policy sequence a try */ ++ if (err != GRUB_ERR_NONE) ++ { ++ /* ++ * Create a basic policy sequence based on the given PCR selection if the ++ * key file doesn't provide one ++ */ ++ if (policy_seq == NULL) ++ { ++ err = grub_tpm2_protector_simple_policy_seq (ctx, &policy_seq); ++ if (err != GRUB_ERR_NONE) ++ goto exit3; ++ } ++ ++ err = grub_tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size); ++ } ++ ++ /* Pop error messages on success */ ++ if (err == GRUB_ERR_NONE) ++ while (grub_error_pop ()); ++ ++exit3: ++ TPM2_FlushContext (sealed_handle); ++ ++exit2: ++ TPM2_FlushContext (srk_handle); ++ ++exit1: ++ grub_tpm2key_free_policy_seq (policy_seq); ++ grub_tpm2key_free_authpolicy_seq (authpol_seq); ++ grub_free (file_bytes); ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx, ++ grub_uint8_t **key, grub_size_t *key_size) ++{ ++ (void)ctx; ++ (void)key; ++ (void)key_size; ++ ++ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, ++ N_("NV Index mode is not implemented yet")); ++} ++ ++static grub_err_t ++grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx, ++ grub_uint8_t **key, grub_size_t *key_size) ++{ ++ switch (ctx->mode) ++ { ++ case GRUB_TPM2_PROTECTOR_MODE_SRK: ++ return grub_tpm2_protector_srk_recover (ctx, key, key_size); ++ case GRUB_TPM2_PROTECTOR_MODE_NV: ++ return grub_tpm2_protector_nv_recover (ctx, key, key_size); ++ default: ++ return GRUB_ERR_BAD_ARGUMENT; ++ } ++} ++ ++static grub_err_t ++grub_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size) ++{ ++ /* Expect a call to tpm2_protector_init before anybody tries to use us */ ++ if (grub_tpm2_protector_ctx.mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) ++ return grub_error (GRUB_ERR_INVALID_COMMAND, ++ N_("Cannot use TPM2 key protector without initializing " ++ "it, call tpm2_protector_init first")); ++ ++ if (key == NULL || key_size == NULL) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ return grub_tpm2_protector_recover (&grub_tpm2_protector_ctx, key, key_size); ++} ++ ++static grub_err_t ++grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) ++{ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) ++ ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK; ++ ++ /* Checks for SRK mode */ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->keyfile == NULL ++ && ctx->tpm2key == NULL) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In SRK mode, a key file must be specified: " ++ "--tpm2key/-T or --keyfile/-k")); ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->keyfile ++ && ctx->tpm2key) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In SRK mode, please specify a key file with " ++ "only --tpm2key/-T or --keyfile/-k")); ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->nv) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In SRK mode, an NV Index cannot be specified")); ++ ++ /* Checks for NV mode */ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->nv == 0) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In NV Index mode, an NV Index must be specified: " ++ "--nvindex or -n")); ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ++ (ctx->tpm2key || ctx->keyfile)) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In NV Index mode, a keyfile cannot be specified")); ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->srk) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In NV Index mode, an SRK cannot be specified")); ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->asymmetric) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("In NV Index mode, an asymmetric key type cannot be " ++ "specified")); ++ ++ /* Defaults assignment */ ++ if (ctx->bank == TPM_ALG_ERROR) ++ ctx->bank = TPM_ALG_SHA256; ++ ++ if (ctx->pcr_count == 0) ++ { ++ ctx->pcrs[0] = 7; ++ ctx->pcr_count = 1; ++ } ++ ++ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK) ++ { ++ if (!ctx->srk) ++ ctx->srk = TPM2_SRK_HANDLE; ++ ++ if (!ctx->asymmetric) ++ ctx->asymmetric = TPM_ALG_RSA; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_parse_file (const char *value, const char **file) ++{ ++ if (grub_strlen (value) == 0) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ *file = grub_strdup (value); ++ if (*file == NULL) ++ return grub_error (GRUB_ERR_OUT_OF_MEMORY, ++ N_("No memory to duplicate file path")); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_parse_mode (const char *value, ++ grub_tpm2_protector_mode_t *mode) ++{ ++ if (grub_strcmp (value, "srk") == 0) ++ *mode = GRUB_TPM2_PROTECTOR_MODE_SRK; ++ else if (grub_strcmp (value, "nv") == 0) ++ *mode = GRUB_TPM2_PROTECTOR_MODE_NV; ++ else ++ return grub_error (GRUB_ERR_OUT_OF_RANGE, ++ N_("Value '%s' is not a valid TPM2 key protector mode"), ++ value); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc, ++ char **args __attribute__ ((unused))) ++{ ++ struct grub_arg_list *state = ctxt->state; ++ grub_err_t err; ++ ++ if (argc) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("The TPM2 key protector does not accept any " ++ "non-option arguments (i.e., like -o and/or --option " ++ "only)")); ++ ++ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); ++ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); ++ ++ if (state[OPTION_MODE].set) /* mode */ ++ { ++ err = grub_tpm2_protector_parse_mode (state[OPTION_MODE].arg, ++ &grub_tpm2_protector_ctx.mode); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_PCRS].set) /* pcrs */ ++ { ++ err = grub_tpm2_protector_parse_pcrs (state[OPTION_PCRS].arg, ++ grub_tpm2_protector_ctx.pcrs, ++ &grub_tpm2_protector_ctx.pcr_count); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_BANK].set) /* bank */ ++ { ++ err = grub_tpm2_protector_parse_bank (state[OPTION_BANK].arg, ++ &grub_tpm2_protector_ctx.bank); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_TPM2KEY].set) /* tpm2key */ ++ { ++ err = grub_tpm2_protector_parse_file (state[OPTION_TPM2KEY].arg, ++ &grub_tpm2_protector_ctx.tpm2key); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_KEYFILE].set) /* keyfile */ ++ { ++ err = grub_tpm2_protector_parse_file (state[OPTION_KEYFILE].arg, ++ &grub_tpm2_protector_ctx.keyfile); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_SRK].set) /* srk */ ++ { ++ err = grub_tpm2_protector_parse_tpm_handle (state[OPTION_SRK].arg, ++ &grub_tpm2_protector_ctx.srk); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_ASYMMETRIC].set) /* asymmetric */ ++ { ++ err = grub_tpm2_protector_parse_asymmetric (state[OPTION_ASYMMETRIC].arg, ++ &grub_tpm2_protector_ctx.asymmetric); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ if (state[OPTION_NVINDEX].set) /* nvindex */ ++ { ++ err = grub_tpm2_protector_parse_tpm_handle (state[OPTION_NVINDEX].arg, ++ &grub_tpm2_protector_ctx.nv); ++ if (err != GRUB_ERR_NONE) ++ return err; ++ } ++ ++ err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); ++ ++ /* This command only initializes the protector, so nothing else to do. */ ++ ++ return err; ++} ++ ++static grub_err_t ++grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ ((unused)), ++ int argc, ++ char **args __attribute__ ((unused))) ++{ ++ if (argc) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ N_("tpm2_key_protector_clear accepts no arguments")); ++ ++ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); ++ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); ++ ++ return GRUB_ERR_NONE; ++} ++ ++static struct grub_key_protector grub_tpm2_key_protector = ++ { ++ .name = "tpm2", ++ .recover_key = grub_tpm2_protector_recover_key ++ }; ++ ++GRUB_MOD_INIT (tpm2) ++{ ++ grub_tpm2_protector_init_cmd = ++ grub_register_extcmd ("tpm2_key_protector_init", ++ grub_tpm2_protector_init_cmd_handler, 0, ++ N_("[-m mode] " ++ "[-p pcr_list] " ++ "[-b pcr_bank] " ++ "[-T tpm2_key_file_path] " ++ "[-k sealed_key_file_path] " ++ "[-s srk_handle] " ++ "[-a asymmetric_key_type] " ++ "[-n nv_index]"), ++ N_("Initialize the TPM2 key protector."), ++ grub_tpm2_protector_init_cmd_options); ++ grub_tpm2_protector_clear_cmd = ++ grub_register_extcmd ("tpm2_key_protector_clear", ++ grub_tpm2_protector_clear_cmd_handler, 0, NULL, ++ N_("Clear the TPM2 key protector if previously initialized."), ++ NULL); ++ grub_key_protector_register (&grub_tpm2_key_protector); ++} ++ ++GRUB_MOD_FINI (tpm2) ++{ ++ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); ++ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); ++ ++ grub_key_protector_unregister (&grub_tpm2_key_protector); ++ grub_unregister_extcmd (grub_tpm2_protector_clear_cmd); ++ grub_unregister_extcmd (grub_tpm2_protector_init_cmd); ++} +diff --git a/grub-core/tpm2/tpm2key.asn b/grub-core/tpm2/tpm2key.asn +new file mode 100644 +index 000000000..e3b6a03e0 +--- /dev/null ++++ b/grub-core/tpm2/tpm2key.asn +@@ -0,0 +1,31 @@ ++-- ++-- TPM 2.0 key file format ++-- To generate tpm2key_asn1_tab.c: asn1Parser tpm2key.asn ++-- ++TPM2KEY {} ++DEFINITIONS IMPLICIT TAGS ::= ++ ++BEGIN ++ ++TPMPolicy ::= SEQUENCE { ++ CommandCode [0] EXPLICIT INTEGER, ++ CommandPolicy [1] EXPLICIT OCTET STRING ++} ++ ++TPMAuthPolicy ::= SEQUENCE { ++ Name [0] EXPLICIT UTF8String OPTIONAL, ++ Policy [1] EXPLICIT SEQUENCE OF TPMPolicy ++} ++ ++TPMKey ::= SEQUENCE { ++ type OBJECT IDENTIFIER, ++ emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, ++ policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, ++ secret [2] EXPLICIT OCTET STRING OPTIONAL, ++ authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, ++ parent INTEGER, ++ pubkey OCTET STRING, ++ privkey OCTET STRING ++} ++ ++END +diff --git a/grub-core/tpm2/tpm2key.c b/grub-core/tpm2/tpm2key.c +new file mode 100644 +index 000000000..62f6d865b +--- /dev/null ++++ b/grub-core/tpm2/tpm2key.c +@@ -0,0 +1,440 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2023 SUSE LLC ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern asn1_static_node tpm2key_asn1_tab[]; ++const char *sealed_key_oid = "2.23.133.10.1.5"; ++ ++static int ++asn1_allocate_and_read (asn1_node node, const char *name, void **content, grub_size_t *content_size) ++{ ++ grub_uint8_t *tmpstr = NULL; ++ int tmpstr_size = 0; ++ int ret; ++ ++ if (content == NULL) ++ return ASN1_MEM_ERROR; ++ ++ ret = asn1_read_value (node, name, NULL, &tmpstr_size); ++ if (ret != ASN1_MEM_ERROR) ++ return ret; ++ ++ tmpstr = grub_malloc (tmpstr_size); ++ if (tmpstr == NULL) ++ return ASN1_MEM_ERROR; ++ ++ ret = asn1_read_value (node, name, tmpstr, &tmpstr_size); ++ if (ret != ASN1_SUCCESS) ++ return ret; ++ ++ *content = tmpstr; ++ *content_size = tmpstr_size; ++ ++ return ASN1_SUCCESS; ++} ++ ++static int ++asn1_read_uint32 (asn1_node node, const char *name, grub_uint32_t *out) ++{ ++ grub_uint32_t tmp = 0; ++ grub_uint8_t *ptr; ++ void *data = NULL; ++ grub_size_t data_size; ++ int ret; ++ ++ ret = asn1_allocate_and_read (node, name, &data, &data_size); ++ if (ret != ASN1_SUCCESS) ++ return ret; ++ ++ if (data_size > 4) ++ { ++ ret = ASN1_MEM_ERROR; ++ goto error; ++ } ++ ++ /* convert the big-endian integer to host uint32 */ ++ ptr = (grub_uint8_t *)&tmp + (4 - data_size); ++ grub_memcpy (ptr, data, data_size); ++ tmp = grub_be_to_cpu32 (tmp); ++ ++ *out = tmp; ++error: ++ if (data) ++ grub_free (data); ++ return ret; ++} ++ ++grub_err_t ++grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size) ++{ ++ asn1_node tpm2key; ++ asn1_node tpm2key_asn1 = NULL; ++ void *type_oid = NULL; ++ grub_size_t type_oid_size = 0; ++ void *empty_auth = NULL; ++ grub_size_t empty_auth_size = 0; ++ int tmp_size = 0; ++ int ret; ++ grub_err_t err; ++ ++ /* ++ TPMKey ::= SEQUENCE { ++ type OBJECT IDENTIFIER, ++ emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, ++ policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, ++ secret [2] EXPLICIT OCTET STRING OPTIONAL, ++ authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, ++ parent INTEGER, ++ pubkey OCTET STRING, ++ privkey OCTET STRING ++ } ++ */ ++ ret = asn1_array2tree (tpm2key_asn1_tab, &tpm2key_asn1, NULL); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ ret = asn1_create_element (tpm2key_asn1, "TPM2KEY.TPMKey", &tpm2key); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ ret = asn1_der_decoding (&tpm2key, data, size, NULL); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ /* Check if 'type' is Sealed Key or not */ ++ ret = asn1_allocate_and_read (tpm2key, "type", &type_oid, &type_oid_size); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_FILE_TYPE; ++ ++ if (grub_memcmp (sealed_key_oid, type_oid, type_oid_size) != 0) ++ { ++ err = GRUB_ERR_BAD_FILE_TYPE; ++ goto error; ++ } ++ ++ /* 'emptyAuth' must be 'TRUE' since we don't support password authorization */ ++ ret = asn1_allocate_and_read (tpm2key, "emptyAuth", &empty_auth, &empty_auth_size); ++ if (ret != ASN1_SUCCESS || grub_strncmp ("TRUE", empty_auth, empty_auth_size) != 0) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* 'secret' should not be in a sealed key */ ++ ret = asn1_read_value (tpm2key, "secret", NULL, &tmp_size); ++ if (ret != ASN1_ELEMENT_NOT_FOUND) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ *parsed_tpm2key = tpm2key; ++ ++ err = GRUB_ERR_NONE; ++ ++error: ++ if (type_oid) ++ grub_free (type_oid); ++ ++ if (empty_auth) ++ grub_free (empty_auth); ++ ++ return err; ++} ++ ++void ++grub_tpm2key_end_parsing (asn1_node tpm2key) ++{ ++ if (tpm2key) ++ asn1_delete_structure (&tpm2key); ++ tpm2key = NULL; ++} ++ ++grub_err_t ++grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent) ++{ ++ int ret; ++ ++ if (parent == NULL) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ if (tpm2key == NULL) ++ return GRUB_ERR_READ_ERROR; ++ ++ ret = asn1_read_uint32 (tpm2key, "parent", parent); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_READ_ERROR; ++ ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++tpm2key_get_octstring (asn1_node tpm2key, const char *name, void **data, grub_size_t *size) ++{ ++ int ret; ++ ++ if (name == NULL || data == NULL || size == NULL) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ if (tpm2key == NULL) ++ return GRUB_ERR_READ_ERROR; ++ ++ ret = asn1_allocate_and_read (tpm2key, name, data, size); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_READ_ERROR; ++ ++ return GRUB_ERR_NONE; ++} ++ ++grub_err_t ++grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size) ++{ ++ return tpm2key_get_octstring (tpm2key, "pubkey", data, size); ++} ++ ++grub_err_t ++grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size) ++{ ++ return tpm2key_get_octstring (tpm2key, "privkey", data, size); ++} ++ ++/* ++ * The string to fetch 'Policy' from 'authPolicy': ++ * authPolicy.?XX.Policy ++ */ ++#define AUTHPOLICY_POL_MAX_STR "authPolicy.?XX.Policy" ++#define AUTHPOLICY_POL_MAX (sizeof (AUTHPOLICY_POL_MAX_STR)) ++ ++/* ++ * Expected strings for CommandCode and CommandPolicy: ++ * policy.?XX.CommandCode ++ * policy.?XX.CommandPolicy ++ * authPolicy.?XX.Policy.?YY.CommandCode ++ * authPolicy.?XX.Policy.?YY.CommandPolicy ++ */ ++#define CMD_CODE_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandCode" ++#define CMD_POL_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandPolicy" ++#define CMD_CODE_MAX (sizeof (CMD_CODE_MAX_STR)) ++#define CMD_POL_MAX (sizeof (CMD_POL_MAX_STR)) ++ ++static int ++tpm2key_get_policy_seq (asn1_node tpm2key, const char *prefix, ++ tpm2key_policy_t *policy_seq) ++{ ++ tpm2key_policy_t tmp_seq = NULL; ++ tpm2key_policy_t policy = NULL; ++ int policy_n; ++ char cmd_code[CMD_CODE_MAX]; ++ char cmd_pol[CMD_POL_MAX]; ++ grub_size_t cmd_policy_len; ++ int i; ++ int ret; ++ ++ ret = asn1_number_of_elements (tpm2key, prefix, &policy_n); ++ if (ret != ASN1_SUCCESS) ++ return ret; ++ ++ /* ++ * Limit the number of policy commands to two digits (99) ++ * Although there is no upper bound for the number of policy commands, ++ * in practice, it takes one or two policy commands to unseal the key, ++ * so the 99 commands limit is more than enough. ++ */ ++ if (policy_n > 100 || policy_n < 1) ++ return ASN1_VALUE_NOT_VALID; ++ ++ /* ++ * Iterate the policy commands backwards since grub_list_push() prepends ++ * the item into the list. ++ */ ++ for (i = policy_n; i >= 1; i--) { ++ policy = grub_zalloc (sizeof (struct tpm2key_policy)); ++ if (policy == NULL) ++ { ++ ret = ASN1_MEM_ALLOC_ERROR; ++ goto error; ++ } ++ grub_snprintf (cmd_code, CMD_CODE_MAX, "%s.?%d.CommandCode", prefix, i); ++ grub_snprintf (cmd_pol, CMD_POL_MAX, "%s.?%d.CommandPolicy", prefix, i); ++ ++ /* CommandCode [0] EXPLICIT INTEGER */ ++ ret = asn1_read_uint32 (tpm2key, cmd_code, &policy->cmd_code); ++ if (ret != ASN1_SUCCESS) ++ return ret; ++ ++ /* CommandPolicy [1] EXPLICIT OCTET STRING */ ++ ret = tpm2key_get_octstring (tpm2key, cmd_pol, &policy->cmd_policy, ++ &cmd_policy_len); ++ if (ret != ASN1_SUCCESS) ++ { ++ goto error; ++ } ++ else if (cmd_policy_len > GRUB_TPM2_BUFFER_CAPACITY) ++ { ++ /* ++ * CommandPolicy is the marshalled parameters for the TPM command so ++ * it should not be larger than the maximum TPM2 buffer. ++ */ ++ ret = ASN1_VALUE_NOT_VALID; ++ goto error; ++ } ++ policy->cmd_policy_len = (grub_uint16_t)cmd_policy_len; ++ ++ /* Prepend the policy command into the sequence */ ++ grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (policy)); ++ } ++ ++ *policy_seq = tmp_seq; ++ ++ return ASN1_SUCCESS; ++ ++error: ++ if (policy) ++ { ++ grub_free (policy->cmd_policy); ++ grub_free (policy); ++ } ++ grub_tpm2key_free_policy_seq (tmp_seq); ++ ++ return ret; ++} ++ ++grub_err_t ++grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq) ++{ ++ int ret; ++ ++ ret = tpm2key_get_policy_seq (tpm2key, "policy", policy_seq); ++ if (ret == ASN1_ELEMENT_NOT_FOUND) ++ { ++ /* "policy" is optional, so it may not be available */ ++ *policy_seq = NULL; ++ return GRUB_ERR_NONE; ++ } ++ else if (ret != ASN1_SUCCESS) ++ { ++ return GRUB_ERR_READ_ERROR; ++ } ++ ++ return GRUB_ERR_NONE; ++} ++ ++void ++grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq) ++{ ++ tpm2key_policy_t policy; ++ tpm2key_policy_t next; ++ ++ if (policy_seq == NULL) ++ return; ++ ++ FOR_LIST_ELEMENTS_SAFE (policy, next, policy_seq) ++ { ++ grub_free (policy->cmd_policy); ++ grub_free (policy); ++ } ++} ++ ++grub_err_t ++grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq) ++{ ++ tpm2key_authpolicy_t tmp_seq = NULL; ++ tpm2key_authpolicy_t authpol = NULL; ++ int authpol_n; ++ char authpol_pol[AUTHPOLICY_POL_MAX]; ++ int i; ++ int ret; ++ grub_err_t err; ++ ++ ret = asn1_number_of_elements (tpm2key, "authPolicy", &authpol_n); ++ if (ret == ASN1_ELEMENT_NOT_FOUND) ++ { ++ /* "authPolicy" is optional, so it may not be available */ ++ *authpol_seq = NULL; ++ return GRUB_ERR_NONE; ++ } ++ else if (ret != ASN1_SUCCESS) ++ { ++ return GRUB_ERR_READ_ERROR; ++ } ++ ++ /* Limit the number of authPolicy elements to two digits (99) */ ++ if (authpol_n > 100 || authpol_n < 1) ++ return GRUB_ERR_OUT_OF_RANGE; ++ ++ /* ++ * Iterate the authPolicy elements backwards since grub_list_push() prepends ++ * the item into the list. ++ */ ++ for (i = authpol_n; i >= 1; i--) { ++ authpol = grub_zalloc (sizeof (struct tpm2key_authpolicy)); ++ if (authpol == NULL) ++ { ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ goto error; ++ } ++ grub_snprintf (authpol_pol, AUTHPOLICY_POL_MAX, "authPolicy.?%d.Policy", i); ++ ++ ret = tpm2key_get_policy_seq (tpm2key, authpol_pol, &authpol->policy_seq); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_READ_ERROR; ++ goto error; ++ } ++ ++ /* Prepend the authPolicy element into the sequence */ ++ grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (authpol)); ++ } ++ ++ *authpol_seq = tmp_seq; ++ ++ return GRUB_ERR_NONE; ++ ++error: ++ if (authpol) ++ { ++ grub_tpm2key_free_policy_seq (authpol->policy_seq); ++ grub_free (authpol); ++ } ++ ++ grub_tpm2key_free_authpolicy_seq (tmp_seq); ++ ++ return err; ++} ++ ++void ++grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq) ++{ ++ tpm2key_authpolicy_t authpol; ++ tpm2key_authpolicy_t next; ++ ++ if (authpol_seq == NULL) ++ return; ++ ++ FOR_LIST_ELEMENTS_SAFE (authpol, next, authpol_seq) ++ { ++ grub_tpm2key_free_policy_seq (authpol->policy_seq); ++ grub_free (authpol); ++ } ++} +diff --git a/grub-core/tpm2/tpm2key_asn1_tab.c b/grub-core/tpm2/tpm2key_asn1_tab.c +new file mode 100644 +index 000000000..551fc46ec +--- /dev/null ++++ b/grub-core/tpm2/tpm2key_asn1_tab.c +@@ -0,0 +1,41 @@ ++/* ++ * This file is generated by 'asn1Parser tpm2key.asn' and the '#include' ++ * headers are replaced with the ones in grub2. ++ * - 'grub/mm.h' for the definition of 'NULL' ++ * - 'grub/libtasn1.h' for the definition of 'asn1_static_node' ++ */ ++ ++#include ++#include ++ ++const asn1_static_node tpm2key_asn1_tab[] = { ++ { "TPM2KEY", 536875024, NULL }, ++ { NULL, 1073741836, NULL }, ++ { "TPMPolicy", 1610612741, NULL }, ++ { "CommandCode", 1610620931, NULL }, ++ { NULL, 2056, "0"}, ++ { "CommandPolicy", 536879111, NULL }, ++ { NULL, 2056, "1"}, ++ { "TPMAuthPolicy", 1610612741, NULL }, ++ { "Name", 1610637346, NULL }, ++ { NULL, 2056, "0"}, ++ { "Policy", 536879115, NULL }, ++ { NULL, 1073743880, "1"}, ++ { NULL, 2, "TPMPolicy"}, ++ { "TPMKey", 536870917, NULL }, ++ { "type", 1073741836, NULL }, ++ { "emptyAuth", 1610637316, NULL }, ++ { NULL, 2056, "0"}, ++ { "policy", 1610637323, NULL }, ++ { NULL, 1073743880, "1"}, ++ { NULL, 2, "TPMPolicy"}, ++ { "secret", 1610637319, NULL }, ++ { NULL, 2056, "2"}, ++ { "authPolicy", 1610637323, NULL }, ++ { NULL, 1073743880, "3"}, ++ { NULL, 2, "TPMAuthPolicy"}, ++ { "parent", 1073741827, NULL }, ++ { "pubkey", 1073741831, NULL }, ++ { "privkey", 7, NULL }, ++ { NULL, 0, NULL } ++}; +diff --git a/include/grub/tpm2/internal/args.h b/include/grub/tpm2/internal/args.h +new file mode 100644 +index 000000000..df3341913 +--- /dev/null ++++ b/include/grub/tpm2/internal/args.h +@@ -0,0 +1,39 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2022 Microsoft Corporation ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER ++#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1 ++ ++#include ++#include ++ ++grub_err_t ++grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, ++ grub_uint8_t *pcr_count); ++ ++grub_err_t ++grub_tpm2_protector_parse_asymmetric (const char *value, ++ TPM_ALG_ID *asymmetric); ++ ++grub_err_t ++grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank); ++ ++grub_err_t ++grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle); ++ ++#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */ +diff --git a/include/grub/tpm2/tpm2key.h b/include/grub/tpm2/tpm2key.h +new file mode 100644 +index 000000000..df46203e3 +--- /dev/null ++++ b/include/grub/tpm2/tpm2key.h +@@ -0,0 +1,83 @@ ++/* ++ * GRUB -- GRand Unified Bootloader ++ * Copyright (C) 2023 SUSE LLC ++ * ++ * GRUB is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * GRUB is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GRUB. If not, see . ++ */ ++ ++#ifndef GRUB_TPM2_TPM2KEY_HEADER ++#define GRUB_TPM2_TPM2KEY_HEADER 1 ++ ++#include ++#include ++ ++/* ++ * TPMPolicy ::= SEQUENCE { ++ * CommandCode [0] EXPLICIT INTEGER, ++ * CommandPolicy [1] EXPLICIT OCTET STRING ++ * } ++ */ ++struct tpm2key_policy { ++ struct tpm2key_policy *next; ++ struct tpm2key_policy **prev; ++ grub_uint32_t cmd_code; ++ void *cmd_policy; ++ grub_uint16_t cmd_policy_len; ++}; ++typedef struct tpm2key_policy *tpm2key_policy_t; ++ ++/* ++ * TPMAuthPolicy ::= SEQUENCE { ++ * Name [0] EXPLICIT UTF8String OPTIONAL, ++ * Policy [1] EXPLICIT SEQUENCE OF TPMPolicy ++ * } ++ * ++ * Name is not a necessary part to unseal the key. Ignore it. ++ */ ++struct tpm2key_authpolicy { ++ struct tpm2key_authpolicy *next; ++ struct tpm2key_authpolicy **prev; ++ /* char *name; */ ++ tpm2key_policy_t policy_seq; ++}; ++typedef struct tpm2key_authpolicy *tpm2key_authpolicy_t; ++ ++grub_err_t ++grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size); ++ ++void ++grub_tpm2key_end_parsing (asn1_node tpm2key); ++ ++grub_err_t ++grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent); ++ ++grub_err_t ++grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size); ++ ++grub_err_t ++grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size); ++ ++grub_err_t ++grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq); ++ ++void ++grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq); ++ ++grub_err_t ++grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq); ++ ++void ++grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq); ++ ++#endif /* GRUB_TPM2_TPM2KEY_HEADER */ +-- +2.35.3 + diff --git a/0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch b/0003-tpm2-Implement-more-TPM2-commands.patch similarity index 97% rename from 0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch rename to 0003-tpm2-Implement-more-TPM2-commands.patch index 43e90b1..b240980 100644 --- a/0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch +++ b/0003-tpm2-Implement-more-TPM2-commands.patch @@ -1,7 +1,7 @@ -From 8f73e30667da46a7716df0f688fbaa41e34fe5ea Mon Sep 17 00:00:00 2001 +From a49c4dcbcb04078434f461ed3356c04042be461a Mon Sep 17 00:00:00 2001 From: Gary Lin Date: Wed, 8 Feb 2023 10:30:55 +0800 -Subject: [PATCH 10/13] tpm2: add TPM2 commands to support authorized policy +Subject: [PATCH 3/4] tpm2: Implement more TPM2 commands This commit implements a few more TPM2 commands as the preparation for the authorized policy support. @@ -27,7 +27,7 @@ Signed-off-by: Gary Lin 2 files changed, 481 insertions(+) diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index a56f7a5e5..2032d6823 100644 +index d67699a24..159353b08 100644 --- a/grub-core/tpm2/tpm2.c +++ b/grub-core/tpm2/tpm2.c @@ -427,6 +427,73 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle, @@ -103,7 +103,7 @@ index a56f7a5e5..2032d6823 100644 + TPM_RC TPM2_Unseal (const TPMI_DH_OBJECT itemHandle, - const TPMS_AUTH_COMMAND *authCommand, + const TPMS_AUTH_COMMAND *authCommand, @@ -759,3 +826,360 @@ TPM2_EvictControl (const TPMI_RH_PROVISION auth, return TPM_RC_SUCCESS; @@ -466,12 +466,12 @@ index a56f7a5e5..2032d6823 100644 + return TPM_RC_SUCCESS; +} diff --git a/include/grub/tpm2/internal/functions.h b/include/grub/tpm2/internal/functions.h -index 8fda8ceab..c8253e4c7 100644 +index 9380f26a2..67b78fab8 100644 --- a/include/grub/tpm2/internal/functions.h +++ b/include/grub/tpm2/internal/functions.h @@ -70,6 +70,15 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle, - TPM2B_NAME *name, - TPMS_AUTH_RESPONSE *authResponse); + TPM2B_NAME *name, + TPMS_AUTH_RESPONSE *authResponse); +TPM_RC +TPM2_LoadExternal (const TPMS_AUTH_COMMAND *authCommand, @@ -484,10 +484,10 @@ index 8fda8ceab..c8253e4c7 100644 + TPM_RC TPM2_Unseal (const TPMI_DH_OBJECT item_handle, - const TPMS_AUTH_COMMAND *authCommand, + const TPMS_AUTH_COMMAND *authCommand, @@ -114,4 +123,52 @@ TPM2_EvictControl (const TPMI_RH_PROVISION auth, - const TPMI_DH_PERSISTENT persistentHandle, - TPMS_AUTH_RESPONSE *authResponse); + const TPMI_DH_PERSISTENT persistentHandle, + TPMS_AUTH_RESPONSE *authResponse); +TPM_RC +TPM2_HashSequenceStart (const TPMS_AUTH_COMMAND *authCommand, diff --git a/0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch b/0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch deleted file mode 100644 index 98657ce..0000000 --- a/0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch +++ /dev/null @@ -1,68 +0,0 @@ -From dcfb996d872a750fc42cb627627a5ac3f6d89a23 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Thu, 9 Feb 2023 14:56:05 +0800 -Subject: [PATCH 03/13] tpm2: resend the command on TPM_RC_RETRY - -Sometimes TPM may return TPM_RC_RETRY for some reason, and the only -thing we can do is to send the command again. To avoid pending in the -while loop indefinitely, just try to send the command 3 times. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/tpm2.c | 33 ++++++++++++++++++++++++++++----- - 1 file changed, 28 insertions(+), 5 deletions(-) - -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 5377ad2c7..083d59d02 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -25,11 +25,11 @@ - #include - - static TPM_RC --grub_tpm2_submit_command (TPMI_ST_COMMAND_TAG tag, -- TPM_CC commandCode, -- TPM_RC* responseCode, -- const struct grub_tpm2_buffer* in, -- struct grub_tpm2_buffer* out) -+grub_tpm2_submit_command_real (const TPMI_ST_COMMAND_TAG tag, -+ const TPM_CC commandCode, -+ TPM_RC *responseCode, -+ const struct grub_tpm2_buffer *in, -+ struct grub_tpm2_buffer *out) - { - grub_err_t err; - struct grub_tpm2_buffer buf; -@@ -75,6 +75,29 @@ grub_tpm2_submit_command (TPMI_ST_COMMAND_TAG tag, - return TPM_RC_SUCCESS; - } - -+static TPM_RC -+grub_tpm2_submit_command (const TPMI_ST_COMMAND_TAG tag, -+ const TPM_CC commandCode, -+ TPM_RC *responseCode, -+ const struct grub_tpm2_buffer *in, -+ struct grub_tpm2_buffer *out) -+{ -+ TPM_RC err; -+ int retry_cnt = 0; -+ -+ /* Catch TPM_RC_RETRY and send the command again */ -+ do { -+ err = grub_tpm2_submit_command_real (tag, commandCode, responseCode, -+ in, out); -+ if (*responseCode != TPM_RC_RETRY) -+ break; -+ -+ retry_cnt++; -+ } while (retry_cnt < 3); -+ -+ return err; -+} -+ - TPM_RC - TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, - const TPMS_AUTH_COMMAND *authCommand, --- -2.35.3 - diff --git a/0013-cryptodisk-Support-key-protectors.patch b/0004-cryptodisk-Support-key-protectors.patch similarity index 100% rename from 0013-cryptodisk-Support-key-protectors.patch rename to 0004-cryptodisk-Support-key-protectors.patch diff --git a/0004-tpm2-Support-authorized-policy.patch b/0004-tpm2-Support-authorized-policy.patch new file mode 100644 index 0000000..8f219d5 --- /dev/null +++ b/0004-tpm2-Support-authorized-policy.patch @@ -0,0 +1,142 @@ +From d6e2d32d53d9a1aac2383fc6c075f3827111b643 Mon Sep 17 00:00:00 2001 +From: Gary Lin +Date: Thu, 6 Apr 2023 16:00:25 +0800 +Subject: [PATCH 4/4] tpm2: Support authorized policy + +TPM2_PolicyAuthorize is the key command to support authorized policy +which allows the users to sign TPM policies with their own keys. + +Per TPM 2.0 Key File(*), CommandPolicy for TPM2_PolicyAuthorize +comprises 'TPM2B_PUBLIC pubkey', 'TPM2B_DIGEST policy_ref', and +'TPMT_SIGNATURE signature'. This commit unmarshals those data +structures, fetches the current policy digest, hashes the policy digest +with the hash algorithm written in 'signature', and then verifies +'signature' with 'pubkey'. If everything goes well, TPM2_PolicyAuthorize +is invoked to authorize the signed policy. + +(*) https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html + +Signed-off-by: Gary Lin +--- + grub-core/tpm2/module.c | 98 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 98 insertions(+) + +diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c +index 5274296b7..e5235c2ac 100644 +--- a/grub-core/tpm2/module.c ++++ b/grub-core/tpm2/module.c +@@ -454,6 +454,101 @@ grub_tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION session, + return GRUB_ERR_NONE; + } + ++static grub_err_t ++grub_tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION session, ++ struct grub_tpm2_buffer *cmd_buf) ++{ ++ TPM2B_PUBLIC pubkey; ++ TPM2B_DIGEST policy_ref; ++ TPMT_SIGNATURE signature; ++ TPM2B_DIGEST pcr_policy; ++ TPM2B_DIGEST pcr_policy_hash; ++ TPMI_ALG_HASH sig_hash; ++ TPMT_TK_VERIFIED verification_ticket; ++ TPM_HANDLE pubkey_handle = 0; ++ TPM2B_NAME pubname; ++ TPM_RC rc; ++ grub_err_t err; ++ ++ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey); ++ grub_tpm2_mu_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref); ++ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature); ++ if (cmd_buf->error != 0) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ return grub_error (err, N_("Failed to unmarshal the buffer for " ++ "TPM2_PolicyAuthorize")); ++ } ++ ++ /* Retrieve Policy Digest */ ++ rc = TPM2_PolicyGetDigest (session, NULL, &pcr_policy, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to get policy digest (TPM error: 0x%x)."), ++ rc); ++ return err; ++ } ++ ++ /* Calculate the digest of the polcy for VerifySignature */ ++ sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature); ++ if (sig_hash == TPM_ALG_NULL) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ grub_error (err, N_("Failed to get the hash algorithm of the signature")); ++ return err; ++ } ++ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, sig_hash, ++ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to create PCR policy hash (TPM2_Hash failed " ++ "with TSS/TPM error %u)"), rc); ++ return err; ++ } ++ ++ /* Load the public key */ ++ rc = TPM2_LoadExternal (NULL, NULL, &pubkey, TPM_RH_OWNER, ++ &pubkey_handle, &pubname, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to load public key (TPM2_LoadExternal failed " ++ "with TSS/TPM error %u)"), rc); ++ return err; ++ } ++ ++ /* Verify the signature against the public key and the policy digest */ ++ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature, ++ &verification_ticket, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to verify signature (TPM2_VerifySignature " ++ "failed with TSS/TPM error %u)"), rc); ++ goto error; ++ } ++ ++ /* Authorize the signed policy with the public key and the verification ticket */ ++ rc = TPM2_PolicyAuthorize (session, NULL, &pcr_policy, &policy_ref, &pubname, ++ &verification_ticket, NULL); ++ if (rc != TPM_RC_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_DEVICE; ++ grub_error (err, N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize " ++ "failed with TSS/TPM error: 0x%u).\n"), rc); ++ goto error; ++ } ++ ++ err = GRUB_ERR_NONE; ++ ++error: ++ TPM2_FlushContext (pubkey_handle); ++ ++ return err; ++} ++ + static grub_err_t + grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION session) + { +@@ -473,6 +568,9 @@ grub_tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSIO + case TPM_CC_PolicyPCR: + err = grub_tpm2_protector_policypcr (session, &buf); + break; ++ case TPM_CC_PolicyAuthorize: ++ err = grub_tpm2_protector_policyauthorize (session, &buf); ++ break; + default: + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Unknown TPM Command: 0x%x"), policy->cmd_code); +-- +2.35.3 + diff --git a/0014-util-grub-protect-Add-new-tool.patch b/0005-util-grub-protect-Add-new-tool.patch similarity index 62% rename from 0014-util-grub-protect-Add-new-tool.patch rename to 0005-util-grub-protect-Add-new-tool.patch index c423a60..57bf0f0 100644 --- a/0014-util-grub-protect-Add-new-tool.patch +++ b/0005-util-grub-protect-Add-new-tool.patch @@ -1,56 +1,73 @@ -From a913983cb75594e08b425e3c099185b2f4187663 Mon Sep 17 00:00:00 2001 +From 38ebade1341ee99593568d97e0300f5b6aa626f3 Mon Sep 17 00:00:00 2001 From: Hernan Gatta Date: Tue, 1 Feb 2022 05:02:57 -0800 -Subject: [PATCH 14/14] util/grub-protect: Add new tool +Subject: [PATCH 5/5] util/grub-protect: Add new tool To utilize the key protectors framework, there must be a way to protect -full-disk encryption keys in the first place. The grub-protect tool includes -support for the TPM2 key protector but other protectors that require setup ahead -of time can be supported in the future. +full-disk encryption keys in the first place. The grub-protect tool +includes support for the TPM2 key protector but other protectors that +require setup ahead of time can be supported in the future. -For the TPM2 key protector, the intended flow is for a user to have a LUKS 1 or -LUKS 2-protected fully-encrypted disk. The user then creates a new key file, say -by reading /dev/urandom into a file, and creates a new LUKS key slot for this -key. Then, the user invokes the grub-protect tool to seal this key file to a set -of PCRs using the system's TPM 2.0. The resulting sealed key file is stored in -an unencrypted partition such as the EFI System Partition (ESP) so that GRUB may -read it. The user also ensures the cryptomount command is included in GRUB's -boot script and that it carries the requisite key protector (-k) parameter. +For the TPM2 key protector, the intended flow is for a user to have a +LUKS 1 or LUKS 2-protected fully-encrypted disk. The user then creates a +new LUKS key file, say by reading /dev/urandom into a file, and creates +a new LUKS key slot for this key. Then, the user invokes the grub-protect +tool to seal this key file to a set of PCRs using the system's TPM 2.0. +The resulting sealed key file is stored in an unencrypted partition such +as the EFI System Partition (ESP) so that GRUB may read it. The user also +ensures the cryptomount command is included in GRUB's boot script and +that it carries the requisite key protector (-P) parameter. Sample usage: -$ dd if=/dev/urandom of=key bs=1 count=32 -$ sudo cryptsetup luksAddKey /dev/sdb1 key --pbkdf=pbkdf2 --hash=sha512 +$ dd if=/dev/urandom of=luks-key bs=1 count=32 +$ sudo cryptsetup luksAddKey /dev/sdb1 luks-key --pbkdf=pbkdf2 --hash=sha512 -$ sudo grub-protect --action=add - --protector=tpm2 - --tpm2-keyfile=key - --tpm2-outfile=/boot/efi/boot/grub2/sealed_key +To seal the key with TPM 2.0 Key File (recommended): -Then, in the boot script: +$ sudo grub-protect --action=add \ + --protector=tpm2 \ + --tpm2key \ + --tpm2-keyfile=luks-key \ + --tpm2-outfile=/boot/efi/boot/grub2/sealed.tpm -tpm2_key_protector_init -k (hd0,gpt1)/boot/grub2/sealed_key -cryptomount -u b20f95d0834842bc9197bd78b36732f8 -k tpm2 +Or, to seal the key with the raw sealed key: + +$ sudo grub-protect --action=add \ + --protector=tpm2 \ + --tpm2-keyfile=luks-key \ + --tpm2-outfile=/boot/efi/boot/grub2/sealed.key + +Then, in the boot script, for TPM 2.0 Key File: + +tpm2_key_protector_init --tpm2key=(hd0,gpt1)/boot/grub2/sealed.tpm +cryptomount -u b20f95d0834842bc9197bd78b36732f8 -P tpm2 + +Or, for the raw sealed key: + +tpm2_key_protector_init --keyfile=(hd0,gpt1)/boot/grub2/sealed.key +cryptomount -u b20f95d0834842bc9197bd78b36732f8 -P tpm2 where the UUID corresponds to /dev/sdb1. Signed-off-by: Hernan Gatta +Signed-off-by: Gary Lin --- - Makefile.util.def | 18 + - configure.ac | 1 + - util/grub-protect.c | 1314 +++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 1334 insertions(+) + .gitignore | 2 + + Makefile.util.def | 22 + + configure.ac | 9 + + util/grub-protect.c | 1508 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 1541 insertions(+) create mode 100644 util/grub-protect.c -diff --git a/Makefile.util.def b/Makefile.util.def -index b3ec2a4bb6..08f681cd8b 100644 ---- a/Makefile.util.def -+++ b/Makefile.util.def -@@ -207,6 +207,24 @@ program = { - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +Index: grub-2.06/Makefile.util.def +=================================================================== +--- grub-2.06.orig/Makefile.util.def ++++ grub-2.06/Makefile.util.def +@@ -207,6 +207,28 @@ program = { }; -+program = { + program = { + name = grub-protect; + + common = grub-core/osdep/init.c; @@ -58,6 +75,7 @@ index b3ec2a4bb6..08f681cd8b 100644 + common = grub-core/tpm2/buffer.c; + common = grub-core/tpm2/mu.c; + common = grub-core/tpm2/tpm2.c; ++ common = grub-core/tpm2/tpm2key_asn1_tab.c; + common = util/grub-protect.c; + common = util/probe.c; + @@ -65,16 +83,20 @@ index b3ec2a4bb6..08f681cd8b 100644 + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ++ ldadd = '$(LIBTASN1)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ++ ++ enable = efi; +}; + - program = { ++program = { name = grub-mkrelpath; mansection = 1; -diff --git a/configure.ac b/configure.ac -index 906eb1cedc..ba717a9600 100644 ---- a/configure.ac -+++ b/configure.ac + +Index: grub-2.06/configure.ac +=================================================================== +--- grub-2.06.orig/configure.ac ++++ grub-2.06/configure.ac @@ -71,6 +71,7 @@ grub_TRANSFORM([grub-mkpasswd-pbkdf2]) grub_TRANSFORM([grub-mkrelpath]) grub_TRANSFORM([grub-mkrescue]) @@ -83,15 +105,30 @@ index 906eb1cedc..ba717a9600 100644 grub_TRANSFORM([grub-reboot]) grub_TRANSFORM([grub-script-check]) grub_TRANSFORM([grub-set-default]) -diff --git a/util/grub-protect.c b/util/grub-protect.c -new file mode 100644 -index 0000000000..23ee78d32a +@@ -1926,6 +1927,14 @@ fi + AC_SUBST([LIBZFS]) + AC_SUBST([LIBNVPAIR]) + ++LIBTASN1= ++if test x"$platform" = xefi; then ++ AC_CHECK_LIB([tasn1], [asn1_write_value], [], ++ [AC_MSG_ERROR([Your platform requires libtasn1])]) ++ LIBTASN1="-ltasn1" ++fi ++AC_SUBST([LIBTASN1]) ++ + LIBS="" + + AC_SUBST([FONT_SOURCE]) +Index: grub-2.06/util/grub-protect.c +=================================================================== --- /dev/null -+++ b/util/grub-protect.c -@@ -0,0 +1,1314 @@ ++++ grub-2.06/util/grub-protect.c +@@ -0,0 +1,1508 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation ++ * Copyright (C) 2023 SUSE LLC + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -111,6 +148,7 @@ index 0000000000..23ee78d32a + +#include +#include ++#include +#include +#include +#include @@ -149,7 +187,8 @@ index 0000000000..23ee78d32a + GRUB_PROTECT_OPT_TPM2_KEYFILE, + GRUB_PROTECT_OPT_TPM2_OUTFILE, + GRUB_PROTECT_OPT_TPM2_PERSIST, -+ GRUB_PROTECT_OPT_TPM2_EVICT ++ GRUB_PROTECT_OPT_TPM2_EVICT, ++ GRUB_PROTECT_OPT_TPM2_TPM2KEY +} grub_protect_opt; + +/* Option flags to keep track of specified arguments */ @@ -167,7 +206,8 @@ index 0000000000..23ee78d32a + GRUB_PROTECT_ARG_TPM2_KEYFILE = 1 << 7, + GRUB_PROTECT_ARG_TPM2_OUTFILE = 1 << 8, + GRUB_PROTECT_ARG_TPM2_PERSIST = 1 << 9, -+ GRUB_PROTECT_ARG_TPM2_EVICT = 1 << 10 ++ GRUB_PROTECT_ARG_TPM2_EVICT = 1 << 10, ++ GRUB_PROTECT_ARG_TPM2_TPM2KEY = 1 << 11 +} grub_protect_arg_t; + +typedef enum grub_protect_protector @@ -199,6 +239,7 @@ index 0000000000..23ee78d32a + const char *tpm2_outfile; + int tpm2_persist; + int tpm2_evict; ++ int tpm2_tpm2key; +}; + +static struct argp_option grub_protect_options[] = @@ -207,19 +248,19 @@ index 0000000000..23ee78d32a + { + .name = "action", + .key = 'a', -+ .arg = "ADD|REMOVE", ++ .arg = "add|remove", + .flags = 0, + .doc = -+ N_("Add or remove a key protector to or from a key."), ++ N_("Add or remove a key protector to or from a key."), + .group = 0 + }, + { + .name = "protector", + .key = 'p', -+ .arg = "TPM2", ++ .arg = "tpm2", + .flags = 0, + .doc = -+ N_("Key protector to use (only TPM2 is currently supported)."), ++ N_("Key protector to use (only tpm2 is currently supported)."), + .group = 0 + }, + /* TPM2 key protector options */ @@ -229,7 +270,7 @@ index 0000000000..23ee78d32a + .arg = "FILE", + .flags = 0, + .doc = -+ N_("Path to the TPM2 device (default is /dev/tpm0)."), ++ N_("Path to the TPM2 device (default is /dev/tpm0)."), + .group = 0 + }, + { @@ -238,8 +279,8 @@ index 0000000000..23ee78d32a + .arg = "0[,1]...", + .flags = 0, + .doc = -+ N_("Comma-separated list of PCRs used to authorize key release " -+ "(e.g., '7,11', default is 7."), ++ N_("Comma-separated list of PCRs used to authorize key release " ++ "(e.g., '7,11', default is 7."), + .group = 0 + }, + { @@ -248,8 +289,8 @@ index 0000000000..23ee78d32a + .arg = "SHA1|SHA256|SHA384", + .flags = 0, + .doc = -+ N_("Bank of PCRs used to authorize key release: " -+ "SHA1, SHA256 (default), or SHA384."), ++ N_("Bank of PCRs used to authorize key release: " ++ "SHA1, SHA256 (default), or SHA384."), + .group = 0 + }, + { @@ -258,7 +299,7 @@ index 0000000000..23ee78d32a + .arg = "FILE", + .flags = 0, + .doc = -+ N_("Path to a file that contains the cleartext key to protect."), ++ N_("Path to a file that contains the cleartext key to protect."), + .group = 0 + }, + { @@ -267,8 +308,8 @@ index 0000000000..23ee78d32a + .arg = "FILE", + .flags = 0, + .doc = -+ N_("Path to the file that will contain the key after sealing (must be " -+ "accessible to GRUB during boot)."), ++ N_("Path to the file that will contain the key after sealing (must be " ++ "accessible to GRUB during boot)."), + .group = 0 + }, + { @@ -277,8 +318,8 @@ index 0000000000..23ee78d32a + .arg = "NUM", + .flags = 0, + .doc = -+ N_("The SRK handle if the SRK is to be made persistent " -+ "(default is 0x81000001)."), ++ N_("The SRK handle if the SRK is to be made persistent " ++ "(default is 0x81000001)."), + .group = 0 + }, + { @@ -287,7 +328,7 @@ index 0000000000..23ee78d32a + .arg = "RSA|ECC", + .flags = 0, + .doc = -+ N_("The type of SRK: RSA (default) or ECC."), ++ N_("The type of SRK: RSA (default) or ECC."), + .group = 0 + }, + { @@ -296,8 +337,8 @@ index 0000000000..23ee78d32a + .arg = NULL, + .flags = 0, + .doc = -+ N_("Whether to persist the SRK onto the TPM, otherwise it is recreated " -+ "ephemerally during boot (default is to not persist it)."), ++ N_("Whether to persist the SRK onto the TPM, otherwise it is recreated " ++ "ephemerally during boot (default is to not persist it)."), + .group = 0 + }, + { @@ -306,7 +347,16 @@ index 0000000000..23ee78d32a + .arg = NULL, + .flags = 0, + .doc = -+ N_("Evict a previously persisted SRK from the TPM, if any."), ++ N_("Evict a previously persisted SRK from the TPM, if any."), ++ .group = 0 ++ }, ++ { ++ .name = "tpm2key", ++ .key = GRUB_PROTECT_OPT_TPM2_TPM2KEY, ++ .arg = NULL, ++ .flags = 0, ++ .doc = ++ N_("Use TPM 2.0 Key File format instead of the raw format."), + .group = 0 + }, + /* End of list */ @@ -317,7 +367,7 @@ index 0000000000..23ee78d32a + +static grub_err_t +grub_protect_read_file (const char *filepath, void **buffer, -+ size_t *buffer_size) ++ size_t *buffer_size) +{ + grub_err_t err; + FILE *f; @@ -325,7 +375,7 @@ index 0000000000..23ee78d32a + void *buf; + + f = fopen (filepath, "rb"); -+ if (!f) ++ if (f == NULL) + return GRUB_ERR_FILE_NOT_FOUND; + + if (fseek (f, 0, SEEK_END)) @@ -335,7 +385,7 @@ index 0000000000..23ee78d32a + } + + len = ftell (f); -+ if (!len) ++ if (len == 0) + { + err = GRUB_ERR_FILE_READ_ERROR; + goto exit1; @@ -344,7 +394,7 @@ index 0000000000..23ee78d32a + rewind (f); + + buf = grub_malloc (len); -+ if (!buf) ++ if (buf == NULL) + { + err = GRUB_ERR_OUT_OF_MEMORY; + goto exit1; @@ -378,7 +428,7 @@ index 0000000000..23ee78d32a + FILE *f; + + f = fopen (filepath, "wb"); -+ if (!f) ++ if (f == NULL) + return GRUB_ERR_FILE_NOT_FOUND; + + if (fwrite (buffer, buffer_size, 1, f) != 1) @@ -411,11 +461,11 @@ index 0000000000..23ee78d32a + int n; + + grub_path = grub_canonicalize_file_name (filepath); -+ if (!grub_path) ++ if (grub_path == NULL) + goto exit1; + + devices = grub_guess_root_devices (grub_path); -+ if (!devices || !devices[0]) ++ if (devices == NULL || devices[0] == NULL) + goto exit2; + + disk = devices[0]; @@ -423,28 +473,28 @@ index 0000000000..23ee78d32a + grub_util_pull_device (disk); + + grub_dev = grub_util_get_grub_dev (disk); -+ if (!grub_dev) ++ if (grub_dev == NULL) + goto exit3; + + dev = grub_device_open (grub_dev); -+ if (!dev) ++ if (dev == NULL) + goto exit4; + + efi_drive = grub_util_guess_efi_drive (disk); -+ if (!efi_drive) ++ if (efi_drive == NULL) + goto exit5; + + partition = grub_partition_get_name (dev->disk->partition); -+ if (!partition) ++ if (partition == NULL) + goto exit6; + + grub_drive_len = grub_strlen (efi_drive) + grub_strlen (partition) + 3; + grub_drive = grub_malloc (grub_drive_len + 1); -+ if (!grub_drive) ++ if (grub_drive == NULL) + goto exit7; + + n = grub_snprintf (grub_drive, grub_drive_len + 1, "(%s,%s)", efi_drive, -+ partition); ++ partition); + if (n != grub_drive_len) + goto exit8; + @@ -480,7 +530,7 @@ index 0000000000..23ee78d32a +grub_err_t +grub_tcg2_get_max_output_size (grub_size_t *size) +{ -+ if (!size) ++ if (size == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + *size = GRUB_TPM2_BUFFER_CAPACITY; @@ -490,10 +540,10 @@ index 0000000000..23ee78d32a + +grub_err_t +grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input, -+ grub_size_t output_size, grub_uint8_t *output) ++ grub_size_t output_size, grub_uint8_t *output) +{ + static const grub_size_t header_size = sizeof (grub_uint16_t) + -+ (2 * sizeof(grub_uint32_t)); ++ (2 * sizeof(grub_uint32_t)); + + if (write (grub_protector_tpm2_fd, input, input_size) != input_size) + return GRUB_ERR_BAD_DEVICE; @@ -529,7 +579,7 @@ index 0000000000..23ee78d32a + return GRUB_ERR_NONE; + + err = close (grub_protector_tpm2_fd); -+ if (err) ++ if (err != GRUB_ERR_NONE) + { + fprintf (stderr, _("Could not close TPM device (Error: %u).\n"), errno); + return GRUB_ERR_IO; @@ -541,16 +591,16 @@ index 0000000000..23ee78d32a + +static grub_err_t +grub_protect_tpm2_get_policy_digest (struct grub_protect_args *args, -+ TPM2B_DIGEST *digest) ++ TPM2B_DIGEST *digest) +{ + TPM_RC rc; + TPML_PCR_SELECTION pcr_sel = { + .count = 1, + .pcrSelections = { + { -+ .hash = args->tpm2_bank, -+ .sizeOfSelect = 3, -+ .pcrSelect = { 0 } ++ .hash = args->tpm2_bank, ++ .sizeOfSelect = 3, ++ .pcrSelect = { 0 } + }, + } + }; @@ -576,10 +626,7 @@ index 0000000000..23ee78d32a + + /* PCR Read */ + for (i = 0; i < args->tpm2_pcr_count; i++) -+ pcr_sel -+ .pcrSelections[0] -+ .pcrSelect[TPM2_PCR_TO_SELECT(args->tpm2_pcrs[i])] -+ |= TPM2_PCR_TO_BIT(args->tpm2_pcrs[i]); ++ TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], args->tpm2_pcrs[i]); + + rc = TPM2_PCR_Read (NULL, &pcr_sel, NULL, &pcr_sel_out, &pcr_values, NULL); + if (rc != TPM_RC_SUCCESS) @@ -590,7 +637,7 @@ index 0000000000..23ee78d32a + + if ((pcr_sel_out.count != pcr_sel.count) || + (pcr_sel.pcrSelections[0].sizeOfSelect != -+ pcr_sel_out.pcrSelections[0].sizeOfSelect)) ++ pcr_sel_out.pcrSelections[0].sizeOfSelect)) + { + fprintf (stderr, _("Could not read all the specified PCRs.\n")); + return GRUB_ERR_BAD_DEVICE; @@ -620,7 +667,7 @@ index 0000000000..23ee78d32a + + pcr_concat_len = pcr_digest_len * args->tpm2_pcr_count; + pcr_concat = grub_malloc (pcr_concat_len); -+ if (!pcr_concat) ++ if (pcr_concat == NULL) + { + err = GRUB_ERR_OUT_OF_MEMORY; + fprintf (stderr, _("Failed to allocate PCR concatenation buffer.\n")); @@ -631,12 +678,12 @@ index 0000000000..23ee78d32a + for (i = 0; i < args->tpm2_pcr_count; i++) + { + if (pcr_values.digests[i].size != pcr_digest_len) -+ { -+ fprintf (stderr, -+ _("Bad PCR value size: expected %lu bytes but got %u bytes.\n"), -+ pcr_digest_len, pcr_values.digests[i].size); -+ goto exit2; -+ } ++ { ++ fprintf (stderr, ++ _("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but got %u bytes.\n"), ++ pcr_digest_len, pcr_values.digests[i].size); ++ goto exit2; ++ } + + grub_memcpy (pcr_cursor, pcr_values.digests[i].buffer, pcr_digest_len); + pcr_cursor += pcr_digest_len; @@ -649,13 +696,13 @@ index 0000000000..23ee78d32a + symmetric.algorithm = TPM_ALG_NULL; + + rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonce, &salt, -+ TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256, -+ &session, NULL, 0); ++ TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256, ++ &session, NULL, 0); + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, -+ _("Failed to start trial policy session (TPM error: 0x%x).\n"), -+ rc); ++ _("Failed to start trial policy session (TPM error: 0x%x).\n"), ++ rc); + err = GRUB_ERR_BAD_DEVICE; + goto exit2; + } @@ -667,7 +714,7 @@ index 0000000000..23ee78d32a + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, _("Failed to submit PCR policy (TPM error: 0x%x).\n"), -+ rc); ++ rc); + err = GRUB_ERR_BAD_DEVICE; + goto exit3; + } @@ -677,7 +724,7 @@ index 0000000000..23ee78d32a + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, _("Failed to get policy digest (TPM error: 0x%x).\n"), -+ rc); ++ rc); + err = GRUB_ERR_BAD_DEVICE; + goto exit3; + } @@ -720,9 +767,9 @@ index 0000000000..23ee78d32a + if (rc == TPM_RC_SUCCESS) + { + if (args->tpm2_persist) -+ fprintf (stderr, -+ _("Warning: --tpm2-persist was specified but the SRK already " -+ "exists on the TPM. Continuing anyway...\n")); ++ fprintf (stderr, ++ _("Warning: --tpm2-persist was specified but the SRK already " ++ "exists on the TPM. Continuing anyway...\n")); + + *srk = TPM2_SRK_HANDLE; + return GRUB_ERR_NONE; @@ -732,8 +779,8 @@ index 0000000000..23ee78d32a + if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) + { + fprintf (stderr, -+ _("The SRK exists on the TPM but its public area cannot be read " -+ "(TPM error: 0x%x).\n"), rc); ++ _("The SRK exists on the TPM but its public area cannot be read " ++ "(TPM error: 0x%x).\n"), rc); + return GRUB_ERR_BAD_DEVICE; + } + @@ -774,9 +821,9 @@ index 0000000000..23ee78d32a + } + + rc = TPM2_CreatePrimary (TPM_RH_OWNER, &authCommand, &inSensitive, &inPublic, -+ &outsideInfo, &creationPcr, &srkHandle, &outPublic, -+ &creationData, &creationHash, &creationTicket, -+ &srkName, NULL); ++ &outsideInfo, &creationPcr, &srkHandle, &outPublic, ++ &creationData, &creationHash, &creationTicket, ++ &srkName, NULL); + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, _("Failed to create SRK (TPM error: 0x%x).\n"), rc); @@ -786,17 +833,17 @@ index 0000000000..23ee78d32a + /* Persist SRK */ + if (args->tpm2_persist) + { -+ rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, args->tpm2_srk, -+ &authCommand, NULL); ++ rc = TPM2_EvictControl (TPM_RH_OWNER, srkHandle, &authCommand, ++ args->tpm2_srk, NULL); + if (rc == TPM_RC_SUCCESS) -+ { -+ TPM2_FlushContext (srkHandle); -+ srkHandle = args->tpm2_srk; -+ } ++ { ++ TPM2_FlushContext (srkHandle); ++ srkHandle = args->tpm2_srk; ++ } + else -+ fprintf (stderr, -+ _("Warning: Failed to persist SRK (TPM error: 0x%x\n). " -+ "Continuing anyway...\n"), rc); ++ fprintf (stderr, ++ _("Warning: Failed to persist SRK (TPM error: 0x%x\n). " ++ "Continuing anyway...\n"), rc); + } + + /* Epilogue */ @@ -807,8 +854,8 @@ index 0000000000..23ee78d32a + +static grub_err_t +grub_protect_tpm2_seal (TPM2B_DIGEST *policyDigest, TPM_HANDLE srk, -+ grub_uint8_t *clearText, grub_size_t clearTextLength, -+ TPM2_SEALED_KEY *sealed_key) ++ grub_uint8_t *clearText, grub_size_t clearTextLength, ++ TPM2_SEALED_KEY *sealed_key) +{ + TPM_RC rc; + TPMS_AUTH_COMMAND authCommand = { 0 }; @@ -831,7 +878,7 @@ index 0000000000..23ee78d32a + inPublic.publicArea.authPolicy = *policyDigest; + + rc = TPM2_Create (srk, &authCommand, &inSensitive, &inPublic, &outsideInfo, -+ &pcr_sel, &outPrivate, &outPublic, NULL, NULL, NULL, NULL); ++ &pcr_sel, &outPrivate, &outPublic, NULL, NULL, NULL, NULL); + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, _("Failed to seal key (TPM error: 0x%x).\n"), rc); @@ -845,9 +892,178 @@ index 0000000000..23ee78d32a + return GRUB_ERR_NONE; +} + ++extern asn1_static_node tpm2key_asn1_tab[]; ++ ++static grub_err_t ++grub_protect_tpm2_export_tpm2key (const struct grub_protect_args *args, ++ TPM2_SEALED_KEY *sealed_key) ++{ ++ const char *sealed_key_oid = "2.23.133.10.1.5"; ++ asn1_node asn1_def = NULL; ++ asn1_node tpm2key = NULL; ++ grub_uint32_t parent; ++ grub_uint32_t cmd_code; ++ struct grub_tpm2_buffer pol_buf; ++ TPML_PCR_SELECTION pcr_sel = { ++ .count = 1, ++ .pcrSelections = { ++ { ++ .hash = args->tpm2_bank, ++ .sizeOfSelect = 3, ++ .pcrSelect = { 0 } ++ }, ++ } ++ }; ++ struct grub_tpm2_buffer pub_buf; ++ struct grub_tpm2_buffer priv_buf; ++ void *der_buf = NULL; ++ int der_buf_size = 0; ++ int i; ++ int ret; ++ grub_err_t err; ++ ++ for (i = 0; i < args->tpm2_pcr_count; i++) ++ TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], args->tpm2_pcrs[i]); ++ ++ /* ++ * Prepare the parameters for TPM_CC_PolicyPCR: ++ * empty pcrDigest and the user selected PCRs ++ */ ++ grub_tpm2_buffer_init (&pol_buf); ++ grub_tpm2_buffer_pack_u16 (&pol_buf, 0); ++ grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&pol_buf, &pcr_sel); ++ ++ grub_tpm2_buffer_init (&pub_buf); ++ grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&pub_buf, &sealed_key->public); ++ grub_tpm2_buffer_init (&priv_buf); ++ grub_tpm2_mu_TPM2B_Marshal (&priv_buf, sealed_key->private.size, ++ sealed_key->private.buffer); ++ if (pub_buf.error != 0 || priv_buf.error != 0) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ ret = asn1_array2tree (tpm2key_asn1_tab, &asn1_def, NULL); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ ret = asn1_create_element (asn1_def, "TPM2KEY.TPMKey" , &tpm2key); ++ if (ret != ASN1_SUCCESS) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ /* Set 'type' to "sealed key" */ ++ ret = asn1_write_value (tpm2key, "type", sealed_key_oid, 1); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Set 'emptyAuth' to TRUE */ ++ ret = asn1_write_value (tpm2key, "emptyAuth", "TRUE", 1); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Set 'policy' */ ++ ret = asn1_write_value (tpm2key, "policy", "NEW", 1); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ cmd_code = grub_cpu_to_be32 (TPM_CC_PolicyPCR); ++ ret = asn1_write_value (tpm2key, "policy.?LAST.CommandCode", &cmd_code, ++ sizeof (cmd_code)); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ret = asn1_write_value (tpm2key, "policy.?LAST.CommandPolicy", &pol_buf.data, ++ pol_buf.size); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Remove 'secret' */ ++ ret = asn1_write_value (tpm2key, "secret", NULL, 0); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Remove 'authPolicy' */ ++ ret = asn1_write_value (tpm2key, "authPolicy", NULL, 0); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Use TPM_RH_OWNER as the default parent handle */ ++ parent = grub_cpu_to_be32 (TPM_RH_OWNER); ++ ret = asn1_write_value (tpm2key, "parent", &parent, sizeof (parent)); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Set the pubkey */ ++ ret = asn1_write_value (tpm2key, "pubkey", pub_buf.data, pub_buf.size); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Set the privkey */ ++ ret = asn1_write_value (tpm2key, "privkey", priv_buf.data, priv_buf.size); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ /* Create the DER binary */ ++ der_buf_size = 0; ++ ret = asn1_der_coding (tpm2key, "", NULL, &der_buf_size, NULL); ++ ++ der_buf = grub_malloc (der_buf_size); ++ if (der_buf == NULL) ++ { ++ err = GRUB_ERR_OUT_OF_MEMORY; ++ goto error; ++ } ++ ++ ret = asn1_der_coding (tpm2key, "", der_buf, &der_buf_size, NULL); ++ if (ret != ASN1_SUCCESS) ++ { ++ err = GRUB_ERR_BAD_ARGUMENT; ++ goto error; ++ } ++ ++ err = grub_protect_write_file (args->tpm2_outfile, der_buf, der_buf_size); ++ if (err != GRUB_ERR_NONE) ++ fprintf (stderr, _("Could not write tpm2key file (Error: %u).\n"), ++ errno); ++ ++error: ++ grub_free (der_buf); ++ ++ if (tpm2key) ++ asn1_delete_structure (&tpm2key); ++ ++ return err; ++} ++ +static grub_err_t +grub_protect_tpm2_export_sealed_key (const char *filepath, -+ TPM2_SEALED_KEY *sealed_key) ++ TPM2_SEALED_KEY *sealed_key) +{ + grub_err_t err; + struct grub_tpm2_buffer buf; @@ -855,14 +1071,14 @@ index 0000000000..23ee78d32a + grub_tpm2_buffer_init (&buf); + grub_tpm2_mu_TPM2B_PUBLIC_Marshal (&buf, &sealed_key->public); + grub_tpm2_mu_TPM2B_Marshal (&buf, sealed_key->private.size, -+ sealed_key->private.buffer); -+ if (buf.error) ++ sealed_key->private.buffer); ++ if (buf.error != 0) + return GRUB_ERR_BAD_ARGUMENT; + + err = grub_protect_write_file (filepath, buf.data, buf.size); -+ if (err) ++ if (err != GRUB_ERR_NONE) + fprintf (stderr, _("Could not write sealed key file (Error: %u).\n"), -+ errno); ++ errno); + + return err; +} @@ -881,36 +1097,39 @@ index 0000000000..23ee78d32a + grub_protect_get_grub_drive_for_file (args->tpm2_outfile, &grub_drive); + + err = grub_protect_tpm2_open_device (args->tpm2_device); -+ if (err) ++ if (err != GRUB_ERR_NONE) + return err; + + err = grub_protect_read_file (args->tpm2_keyfile, (void **)&key, &key_size); -+ if (err) ++ if (err != GRUB_ERR_NONE) + goto exit1; + + if (key_size > TPM_MAX_SYM_DATA) + { + fprintf (stderr, -+ _("Input key is too long, maximum allowed size is %u bytes.\n"), -+ TPM_MAX_SYM_DATA); ++ _("Input key is too long, maximum allowed size is %u bytes.\n"), ++ TPM_MAX_SYM_DATA); + return GRUB_ERR_OUT_OF_RANGE; + } + + err = grub_protect_tpm2_get_srk (args, &srk); -+ if (err) ++ if (err != GRUB_ERR_NONE) + goto exit2; + + err = grub_protect_tpm2_get_policy_digest (args, &policy_digest); -+ if (err) ++ if (err != GRUB_ERR_NONE) + goto exit3; + + err = grub_protect_tpm2_seal (&policy_digest, srk, key, key_size, -+ &sealed_key); -+ if (err) ++ &sealed_key); ++ if (err != GRUB_ERR_NONE) + goto exit3; + -+ err = grub_protect_tpm2_export_sealed_key (args->tpm2_outfile, &sealed_key); -+ if (err) ++ if (args->tpm2_tpm2key) ++ err = grub_protect_tpm2_export_tpm2key (args, &sealed_key); ++ else ++ err = grub_protect_tpm2_export_sealed_key (args->tpm2_outfile, &sealed_key); ++ if (err != GRUB_ERR_NONE) + goto exit3; + + if (grub_drive) @@ -921,8 +1140,8 @@ index 0000000000..23ee78d32a + else + { + fprintf (stderr, -+ _("Warning: Could not determine GRUB drive for sealed key " -+ "file.\n")); ++ _("Warning: Could not determine GRUB drive for sealed key " ++ "file.\n")); + err = GRUB_ERR_NONE; + } + @@ -946,14 +1165,14 @@ index 0000000000..23ee78d32a + TPMS_AUTH_COMMAND authCommand = { 0 }; + grub_err_t err; + -+ if (!args->tpm2_evict) ++ if (args->tpm2_evict == 0) + { + printf (_("--tpm2-evict not specified, nothing to do.\n")); + return GRUB_ERR_NONE; + } + + err = grub_protect_tpm2_open_device (args->tpm2_device); -+ if (err) ++ if (err != GRUB_ERR_NONE) + return err; + + /* Find SRK */ @@ -968,13 +1187,13 @@ index 0000000000..23ee78d32a + /* Evict SRK */ + authCommand.sessionHandle = TPM_RS_PW; + -+ rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, args->tpm2_srk, -+ &authCommand, NULL); ++ rc = TPM2_EvictControl (TPM_RH_OWNER, args->tpm2_srk, &authCommand, ++ args->tpm2_srk, NULL); + if (rc != TPM_RC_SUCCESS) + { + fprintf (stderr, -+ _("Failed to evict SRK with handle 0x%x (TPM Error: 0x%x).\n"), -+ args->tpm2_srk, rc); ++ _("Failed to evict SRK with handle 0x%x (TPM Error: 0x%x).\n"), ++ args->tpm2_srk, rc); + err = GRUB_ERR_BAD_DEVICE; + goto exit2; + } @@ -1013,99 +1232,99 @@ index 0000000000..23ee78d32a + { + case GRUB_PROTECT_ACTION_ADD: + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT) -+ { -+ fprintf (stderr, -+ _("--tpm2-evict is invalid when --action is 'add'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-evict is invalid when --action is 'add'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + -+ if (!args->tpm2_keyfile) -+ { -+ fprintf (stderr, _("--tpm2-keyfile must be specified.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ if (args->tpm2_keyfile == NULL) ++ { ++ fprintf (stderr, _("--tpm2-keyfile must be specified.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + -+ if (!args->tpm2_outfile) -+ { -+ fprintf (stderr, _("--tpm2-outfile must be specified.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ if (args->tpm2_outfile == NULL) ++ { ++ fprintf (stderr, _("--tpm2-outfile must be specified.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + -+ if (!args->tpm2_device) -+ args->tpm2_device = "/dev/tpm0"; ++ if (args->tpm2_device == NULL) ++ args->tpm2_device = "/dev/tpm0"; + -+ if (!args->tpm2_pcr_count) -+ { -+ args->tpm2_pcrs[0] = 7; -+ args->tpm2_pcr_count = 1; -+ } ++ if (args->tpm2_pcr_count == 0) ++ { ++ args->tpm2_pcrs[0] = 7; ++ args->tpm2_pcr_count = 1; ++ } + -+ if (!args->tpm2_srk) -+ args->tpm2_srk = TPM2_SRK_HANDLE; ++ if (args->tpm2_srk == 0) ++ args->tpm2_srk = TPM2_SRK_HANDLE; + -+ if (!args->tpm2_asymmetric) -+ args->tpm2_asymmetric = TPM_ALG_RSA; ++ if (args->tpm2_asymmetric == TPM_ALG_ERROR) ++ args->tpm2_asymmetric = TPM_ALG_RSA; + -+ if (!args->tpm2_bank) -+ args->tpm2_bank = TPM_ALG_SHA256; ++ if (args->tpm2_bank == TPM_ALG_ERROR) ++ args->tpm2_bank = TPM_ALG_SHA256; + + break; + + case GRUB_PROTECT_ACTION_REMOVE: + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC) -+ { -+ fprintf (stderr, -+ _("--tpm2-asymmetric is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-asymmetric is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK) -+ { -+ fprintf (stderr, -+ _("--tpm2-bank is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-bank is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE) -+ { -+ fprintf (stderr, -+ _("--tpm2-keyfile is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-keyfile is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE) -+ { -+ fprintf (stderr, -+ _("--tpm2-outfile is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-outfile is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS) -+ { -+ fprintf (stderr, -+ _("--tpm2-pcrs is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-pcrs is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST) -+ { -+ fprintf (stderr, -+ _("--tpm2-persist is invalid when --action is 'remove'.\n")); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } ++ { ++ fprintf (stderr, ++ _("--tpm2-persist is invalid when --action is 'remove'.\n")); ++ return GRUB_ERR_BAD_ARGUMENT; ++ } + -+ if (!args->tpm2_device) -+ args->tpm2_device = "/dev/tpm0"; ++ if (args->tpm2_device == NULL) ++ args->tpm2_device = "/dev/tpm0"; + -+ if (!args->tpm2_srk) -+ args->tpm2_srk = TPM2_SRK_HANDLE; ++ if (args->tpm2_srk == 0) ++ args->tpm2_srk = TPM2_SRK_HANDLE; + + break; + + default: + fprintf (stderr, -+ _("The TPM2 key protector only supports the following actions: " -+ "add, remove.\n")); ++ _("The TPM2 key protector only supports the following actions: " ++ "add, remove.\n")); + return GRUB_ERR_BAD_ARGUMENT; + } + @@ -1122,48 +1341,48 @@ index 0000000000..23ee78d32a + { + case GRUB_PROTECT_OPT_ACTION: + if (args->args & GRUB_PROTECT_ARG_ACTION) -+ { -+ fprintf (stderr, _("--action|-a can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--action|-a can only be specified once.\n")); ++ return EINVAL; ++ } + + if (grub_strcmp (arg, "add") == 0) -+ args->action = GRUB_PROTECT_ACTION_ADD; ++ args->action = GRUB_PROTECT_ACTION_ADD; + else if (grub_strcmp (arg, "remove") == 0) -+ args->action = GRUB_PROTECT_ACTION_REMOVE; ++ args->action = GRUB_PROTECT_ACTION_REMOVE; + else -+ { -+ fprintf (stderr, _("'%s' is not a valid action.\n"), arg); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("'%s' is not a valid action.\n"), arg); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_ACTION; + break; + + case GRUB_PROTECT_OPT_PROTECTOR: + if (args->args & GRUB_PROTECT_ARG_PROTECTOR) -+ { -+ fprintf (stderr, _("--protector|-p can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--protector|-p can only be specified once.\n")); ++ return EINVAL; ++ } + + if (grub_strcmp (arg, "tpm2") == 0) -+ args->protector = GRUB_PROTECT_TYPE_TPM2; ++ args->protector = GRUB_PROTECT_TYPE_TPM2; + else -+ { -+ fprintf (stderr, _("'%s' is not a valid protector.\n"), arg); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("'%s' is not a valid protector.\n"), arg); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_PROTECTOR; + break; + + case GRUB_PROTECT_OPT_TPM2_DEVICE: + if (args->args & GRUB_PROTECT_ARG_TPM2_DEVICE) -+ { -+ fprintf (stderr, _("--tpm2-device can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-device can only be specified once.\n")); ++ return EINVAL; ++ } + + args->tpm2_device = xstrdup(arg); + args->args |= GRUB_PROTECT_ARG_TPM2_DEVICE; @@ -1171,83 +1390,83 @@ index 0000000000..23ee78d32a + + case GRUB_PROTECT_OPT_TPM2_PCRS: + if (args->args & GRUB_PROTECT_ARG_TPM2_PCRS) -+ { -+ fprintf (stderr, _("--tpm2-pcrs can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-pcrs can only be specified once.\n")); ++ return EINVAL; ++ } + + err = grub_tpm2_protector_parse_pcrs (arg, args->tpm2_pcrs, -+ &args->tpm2_pcr_count); -+ if (err) -+ { -+ if (grub_errno) -+ grub_print_error (); -+ return EINVAL; -+ } ++ &args->tpm2_pcr_count); ++ if (err != GRUB_ERR_NONE) ++ { ++ if (grub_errno != GRUB_ERR_NONE) ++ grub_print_error (); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_TPM2_PCRS; + break; + + case GRUB_PROTECT_OPT_TPM2_SRK: + if (args->args & GRUB_PROTECT_ARG_TPM2_SRK) -+ { -+ fprintf (stderr, _("--tpm2-srk can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-srk can only be specified once.\n")); ++ return EINVAL; ++ } + + err = grub_tpm2_protector_parse_tpm_handle (arg, &args->tpm2_srk); -+ if (err) -+ { -+ if (grub_errno) -+ grub_print_error (); -+ return EINVAL; -+ } ++ if (err != GRUB_ERR_NONE) ++ { ++ if (grub_errno != GRUB_ERR_NONE) ++ grub_print_error (); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_TPM2_SRK; + break; + + case GRUB_PROTECT_OPT_TPM2_ASYMMETRIC: + if (args->args & GRUB_PROTECT_ARG_TPM2_ASYMMETRIC) -+ { -+ fprintf (stderr, _("--tpm2-asymmetric can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-asymmetric can only be specified once.\n")); ++ return EINVAL; ++ } + + err = grub_tpm2_protector_parse_asymmetric (arg, &args->tpm2_asymmetric); -+ if (err) -+ { -+ if (grub_errno) -+ grub_print_error (); -+ return EINVAL; -+ } ++ if (err != GRUB_ERR_NONE) ++ { ++ if (grub_errno != GRUB_ERR_NONE) ++ grub_print_error (); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_TPM2_ASYMMETRIC; + break; + + case GRUB_PROTECT_OPT_TPM2_BANK: + if (args->args & GRUB_PROTECT_ARG_TPM2_BANK) -+ { -+ fprintf (stderr, _("--tpm2-bank can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-bank can only be specified once.\n")); ++ return EINVAL; ++ } + + err = grub_tpm2_protector_parse_bank (arg, &args->tpm2_bank); -+ if (err) -+ { -+ if (grub_errno) -+ grub_print_error (); -+ return EINVAL; -+ } ++ if (err != GRUB_ERR_NONE) ++ { ++ if (grub_errno != GRUB_ERR_NONE) ++ grub_print_error (); ++ return EINVAL; ++ } + + args->args |= GRUB_PROTECT_ARG_TPM2_BANK; + break; + + case GRUB_PROTECT_OPT_TPM2_KEYFILE: + if (args->args & GRUB_PROTECT_ARG_TPM2_KEYFILE) -+ { -+ fprintf (stderr, _("--tpm2-keyfile can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-keyfile can only be specified once.\n")); ++ return EINVAL; ++ } + + args->tpm2_keyfile = xstrdup(arg); + args->args |= GRUB_PROTECT_ARG_TPM2_KEYFILE; @@ -1255,10 +1474,10 @@ index 0000000000..23ee78d32a + + case GRUB_PROTECT_OPT_TPM2_OUTFILE: + if (args->args & GRUB_PROTECT_ARG_TPM2_OUTFILE) -+ { -+ fprintf (stderr, _("--tpm2-outfile can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-outfile can only be specified once.\n")); ++ return EINVAL; ++ } + + args->tpm2_outfile = xstrdup(arg); + args->args |= GRUB_PROTECT_ARG_TPM2_OUTFILE; @@ -1266,10 +1485,10 @@ index 0000000000..23ee78d32a + + case GRUB_PROTECT_OPT_TPM2_PERSIST: + if (args->args & GRUB_PROTECT_ARG_TPM2_PERSIST) -+ { -+ fprintf (stderr, _("--tpm2-persist can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-persist can only be specified once.\n")); ++ return EINVAL; ++ } + + args->tpm2_persist = 1; + args->args |= GRUB_PROTECT_ARG_TPM2_PERSIST; @@ -1277,15 +1496,26 @@ index 0000000000..23ee78d32a + + case GRUB_PROTECT_OPT_TPM2_EVICT: + if (args->args & GRUB_PROTECT_ARG_TPM2_EVICT) -+ { -+ fprintf (stderr, _("--tpm2-evict can only be specified once.\n")); -+ return EINVAL; -+ } ++ { ++ fprintf (stderr, _("--tpm2-evict can only be specified once.\n")); ++ return EINVAL; ++ } + + args->tpm2_evict = 1; + args->args |= GRUB_PROTECT_ARG_TPM2_EVICT; + break; + ++ case GRUB_PROTECT_OPT_TPM2_TPM2KEY: ++ if (args->args & GRUB_PROTECT_ARG_TPM2_TPM2KEY) ++ { ++ fprintf (stderr, _("--tpm2-tpm2key can only be specified once.\n")); ++ return EINVAL; ++ } ++ ++ args->tpm2_tpm2key = 1; ++ args->args |= GRUB_PROTECT_ARG_TPM2_TPM2KEY; ++ break; ++ + default: + return ARGP_ERR_UNKNOWN; + } @@ -1307,8 +1537,8 @@ index 0000000000..23ee78d32a + if (args->protector != GRUB_PROTECT_TYPE_TPM2) + { + fprintf (stderr, -+ _("--protector is mandatory and only 'tpm2' is currently " -+ "supported.\n")); ++ _("--protector is mandatory and only 'tpm2' is currently " ++ "supported.\n")); + return GRUB_ERR_BAD_ARGUMENT; + } + @@ -1391,11 +1621,11 @@ index 0000000000..23ee78d32a + grub_protect_init (&argc, &argv); + + err = grub_protect_args_verify (&args); -+ if (err) ++ if (err != GRUB_ERR_NONE) + goto exit; + + err = grub_protect_dispatch (&args); -+ if (err) ++ if (err != GRUB_ERR_NONE) + goto exit; + +exit: @@ -1403,6 +1633,3 @@ index 0000000000..23ee78d32a + + return err; +} --- -2.34.1 - diff --git a/0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch b/0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch deleted file mode 100644 index 3055503..0000000 --- a/0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 4cde0a1bfb8382677c331e0cf4fa482afadbfa1f Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Tue, 7 Feb 2023 18:37:25 +0800 -Subject: [PATCH 06/13] tpm2: check the command parameters of TPM2 commands - -Some command parameters should not be NULL. Add the conditional check to -avoid the potential NULL pointer reference. - -Besides, for TPM2_StartAuthSession, when 'tpmKey' is 'TPM_RH_NULL', the -size of 'encryptedSalt' must be 0 per "TCG TPM2 Part3 Commands". - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/tpm2.c | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 1176d968b..8a98fa251 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -127,6 +127,9 @@ TPM2_CreatePrimary (const TPMI_RH_HIERARCHY primaryHandle, - TPM_RC responseCode; - grub_uint32_t parameterSize; - -+ if (!inSensitive || !inPublic || !outsideInfo || !creationPCR) -+ return TPM_RC_VALUE; -+ - if (!objectHandle) - objectHandle = &objectHandleTmp; - if (!outPublic) -@@ -210,6 +213,13 @@ TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, - TPM_RC responseCode; - grub_uint32_t param_size; - -+ if (!nonceCaller || !symmetric) -+ return TPM_RC_VALUE; -+ -+ if (tpmKey == TPM_RH_NULL && -+ (encryptedSalt && encryptedSalt->size != 0)) -+ return TPM_RC_VALUE; -+ - if (!sessionHandle) - sessionHandle = &sessionHandleTmp; - if (!nonceTpm) -@@ -272,6 +282,9 @@ TPM2_PolicyPCR (const TPMI_SH_POLICY policySessions, - TPM_RC responseCode; - grub_uint32_t param_size; - -+ if (!pcrs) -+ return TPM_RC_VALUE; -+ - if (!authResponse) - authResponse = &authResponseTmp; - -@@ -363,6 +376,9 @@ TPM2_Load (const TPMI_DH_OBJECT parent_handle, - TPM_RC responseCode; - grub_uint32_t param_size; - -+ if (!inPrivate || !inPublic) -+ return TPM_RC_VALUE; -+ - if (!objectHandle) - objectHandle = &objectHandleTmp; - if (!name) -@@ -506,7 +522,7 @@ TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, - grub_uint32_t parameterSize; - - if (!pcrSelectionIn) -- return TPM_RC_FAILURE; -+ return TPM_RC_VALUE; - - if (!pcrUpdateCounter) - pcrUpdateCounter = &pcrUpdateCounterTmp; -@@ -625,6 +641,9 @@ TPM2_Create (const TPMI_DH_OBJECT parentHandle, - TPM_RC rc; - grub_uint32_t parameterSize; - -+ if (!inSensitive || !inPublic || !outsideInfo || !creationPCR) -+ return TPM_RC_VALUE; -+ - if (!outPrivate) - outPrivate = &outPrivateTmp; - if (!outPublic) --- -2.35.3 - diff --git a/0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch b/0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch deleted file mode 100644 index 8069a47..0000000 --- a/0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4f00de963f3cf483d4067cdf0e86147248e9456e Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 8 Feb 2023 15:12:10 +0800 -Subject: [PATCH 07/13] tpm2: pack the missing authorization command for - TPM2_PCR_Read - -When the caller of TPM2_PCR_Read() passes a valid authorization command, -we should pack it into the 'in' buffer before sending the command. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/tpm2.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 8a98fa251..8081b8bf3 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -535,6 +535,8 @@ TPM2_PCR_Read (const TPMS_AUTH_COMMAND *authCommand, - - /* Marshal */ - grub_tpm2_buffer_init (&in); -+ if (authCommand) -+ grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); - grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, pcrSelectionIn); - if (in.error) - return TPM_RC_FAILURE; --- -2.35.3 - diff --git a/0008-tpm2-allow-some-command-parameters-to-be-NULL.patch b/0008-tpm2-allow-some-command-parameters-to-be-NULL.patch deleted file mode 100644 index 61a5945..0000000 --- a/0008-tpm2-allow-some-command-parameters-to-be-NULL.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 6a280321880fffed8765d65226b92f991443dbc6 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Tue, 7 Feb 2023 22:47:50 +0800 -Subject: [PATCH 08/13] tpm2: allow some command parameters to be NULL - -There are some parameters of TPM2 commmands allowing to be empty such -as 'encryptedSalt' of 'TPM2_StartAuthSession' and 'pcrDigest' of -'TPM2_PolicyPCR'. Instead of forcing the user of those functions to -declare an empty variable, we can just pack a u16 zero to fabricate an -empty variable when the user passes NULL for them. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/tpm2.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/grub-core/tpm2/tpm2.c b/grub-core/tpm2/tpm2.c -index 8081b8bf3..a56f7a5e5 100644 ---- a/grub-core/tpm2/tpm2.c -+++ b/grub-core/tpm2/tpm2.c -@@ -238,7 +238,10 @@ TPM2_StartAuthSession (const TPMI_DH_OBJECT tpmKey, - if (tag == TPM_ST_SESSIONS) - grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); - grub_tpm2_mu_TPM2B_Marshal (&in, nonceCaller->size, nonceCaller->buffer); -- grub_tpm2_mu_TPM2B_Marshal (&in, encryptedSalt->size, encryptedSalt->secret); -+ if (encryptedSalt) -+ grub_tpm2_mu_TPM2B_Marshal (&in, encryptedSalt->size, encryptedSalt->secret); -+ else -+ grub_tpm2_buffer_pack_u16 (&in, 0); - grub_tpm2_buffer_pack_u8 (&in, sessionType); - grub_tpm2_mu_TPMT_SYM_DEF_Marshal (&in, symmetric); - grub_tpm2_buffer_pack_u16 (&in, authHash); -@@ -295,7 +298,10 @@ TPM2_PolicyPCR (const TPMI_SH_POLICY policySessions, - grub_tpm2_buffer_pack_u32 (&in, policySessions); - if (tag == TPM_ST_SESSIONS) - grub_tpm2_mu_TPMS_AUTH_COMMAND_Marshal (&in, authCommand); -- grub_tpm2_mu_TPM2B_Marshal (&in, pcrDigest->size, pcrDigest->buffer); -+ if (pcrDigest) -+ grub_tpm2_mu_TPM2B_Marshal (&in, pcrDigest->size, pcrDigest->buffer); -+ else -+ grub_tpm2_buffer_pack_u16 (&in, 0); - grub_tpm2_mu_TPML_PCR_SELECTION_Marshal (&in, pcrs); - if (in.error) - return TPM_RC_FAILURE; --- -2.35.3 - diff --git a/0009-tpm2-remove-the-unnecessary-variables.patch b/0009-tpm2-remove-the-unnecessary-variables.patch deleted file mode 100644 index 023a9c3..0000000 --- a/0009-tpm2-remove-the-unnecessary-variables.patch +++ /dev/null @@ -1,44 +0,0 @@ -From ffb0fe8f2dc9256af6df2e3199e3f950e6b8b830 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 8 Feb 2023 10:35:49 +0800 -Subject: [PATCH 09/13] tpm2: remove the unnecessary variables - -Since the NULL 'encryptedSalt' of 'TPM2_StartAuthSession' is handled as -an empty TPM2B structure, there is no need to declare an empty salt. -As for 'nonceTPM', we don't use in the following TPM2 commands, so we -can safely ignore it. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/module.c | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c -index 8ede48bbf..3537f223c 100644 ---- a/grub-core/tpm2/module.c -+++ b/grub-core/tpm2/module.c -@@ -352,9 +352,7 @@ grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - grub_size_t sealed_key_size; - TPM_HANDLE srk_handle; - TPM2B_NONCE nonceCaller = { 0 }; -- TPM2B_ENCRYPTED_SECRET salt = { 0 }; - TPMT_SYM_DEF symmetric = { 0 }; -- TPM2B_NONCE nonceTPM = { 0 }; - TPMI_SH_AUTH_SESSION session; - TPML_PCR_SELECTION pcrSel = { - .count = 1, -@@ -405,9 +403,9 @@ grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - nonceCaller.size = TPM_SHA256_DIGEST_SIZE; - symmetric.algorithm = TPM_ALG_NULL; - -- rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonceCaller, &salt, -+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonceCaller, NULL, - TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, -- &session, &nonceTPM, 0); -+ &session, NULL, NULL); - if (rc) - { - grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession " --- -2.35.3 - diff --git a/0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch b/0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch deleted file mode 100644 index ebdee88..0000000 --- a/0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch +++ /dev/null @@ -1,135 +0,0 @@ -From e144e2b256ae9771306a8df04f8b9289d435349b Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 8 Feb 2023 11:17:18 +0800 -Subject: [PATCH 11/13] tpm2: make the file reading/unmarshal functions generic - -Both the key file reading function and the key unmarshal function are -also needed for the authorized policy mode. Slightly modify those -functions so that we can reuse them for the authorized policy mode. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/module.c | 67 ++++++++++++++++++++--------------------- - 1 file changed, 33 insertions(+), 34 deletions(-) - -diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c -index 3537f223c..b404d8449 100644 ---- a/grub-core/tpm2/module.c -+++ b/grub-core/tpm2/module.c -@@ -144,20 +144,20 @@ static grub_extcmd_t grub_tpm2_protector_clear_cmd; - static struct grub_tpm2_protector_context grub_tpm2_protector_ctx = { 0 }; - - static grub_err_t --grub_tpm2_protector_srk_read_keyfile (const char *filepath, void **buffer, -- grub_size_t *buffer_size) -+grub_tpm2_protector_read_file (const char *filepath, void **buffer, -+ grub_size_t *buffer_size) - { -- grub_file_t sealed_key_file; -- grub_off_t sealed_key_size; -- void *sealed_key_buffer; -- grub_off_t sealed_key_read; -+ grub_file_t file; -+ grub_off_t file_size; -+ void *file_buffer; -+ grub_off_t file_read; - - /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9 - * otherwise we'll never be able to predict the value of PCR9 at unseal time */ -- sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); -- if (!sealed_key_file) -+ file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); -+ if (!file) - { -- grub_dprintf ("tpm2", "Could not open sealed key file.\n"); -+ grub_dprintf ("tpm2", "Could not open file: %s\n", filepath); - /* grub_file_open sets grub_errno on error, and if we do no unset it, - * future calls to grub_file_open will fail (and so will anybody up the - * stack who checks the value, if any). */ -@@ -165,44 +165,43 @@ grub_tpm2_protector_srk_read_keyfile (const char *filepath, void **buffer, - return GRUB_ERR_FILE_NOT_FOUND; - } - -- sealed_key_size = grub_file_size (sealed_key_file); -- if (!sealed_key_size) -+ file_size = grub_file_size (file); -+ if (!file_size) - { -- grub_dprintf ("tpm2", "Could not read sealed key file size.\n"); -- grub_file_close (sealed_key_file); -+ grub_dprintf ("tpm2", "Could not read file size: %s\n", filepath); -+ grub_file_close (file); - return GRUB_ERR_OUT_OF_RANGE; - } - -- sealed_key_buffer = grub_malloc (sealed_key_size); -- if (!sealed_key_buffer) -+ file_buffer = grub_malloc (file_size); -+ if (!file_buffer) - { -- grub_dprintf ("tpm2", "Could not allocate buffer for sealed key.\n"); -- grub_file_close (sealed_key_file); -+ grub_dprintf ("tpm2", "Could not allocate buffer: %s\n", filepath); -+ grub_file_close (file); - return GRUB_ERR_OUT_OF_MEMORY; - } - -- sealed_key_read = grub_file_read (sealed_key_file, sealed_key_buffer, -- sealed_key_size); -- if (sealed_key_read != sealed_key_size) -+ file_read = grub_file_read (file, file_buffer, file_size); -+ if (file_read != file_size) - { -- grub_dprintf ("tpm2", "Could not retrieve sealed key file contents.\n"); -- grub_free (sealed_key_buffer); -- grub_file_close (sealed_key_file); -+ grub_dprintf ("tpm2", "Could not retrieve file contents: %s\n", filepath); -+ grub_free (file_buffer); -+ grub_file_close (file); - return GRUB_ERR_FILE_READ_ERROR; - } - -- grub_file_close (sealed_key_file); -+ grub_file_close (file); - -- *buffer = sealed_key_buffer; -- *buffer_size = sealed_key_size; -+ *buffer = file_buffer; -+ *buffer_size = file_size; - - return GRUB_ERR_NONE; - } - - static grub_err_t --grub_tpm2_protector_srk_unmarshal_keyfile (void *sealed_key, -- grub_size_t sealed_key_size, -- TPM2_SEALED_KEY *sk) -+grub_tpm2_protector_unmarshal_keyfile (void *sealed_key, -+ grub_size_t sealed_key_size, -+ TPM2_SEALED_KEY *sk) - { - struct grub_tpm2_buffer buf; - -@@ -374,14 +373,14 @@ grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - grub_err_t err; - - /* Retrieve Sealed Key */ -- err = grub_tpm2_protector_srk_read_keyfile (ctx->keyfile, &sealed_key_bytes, -- &sealed_key_size); -+ err = grub_tpm2_protector_read_file (ctx->keyfile, &sealed_key_bytes, -+ &sealed_key_size); - if (err) - return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile); - -- err = grub_tpm2_protector_srk_unmarshal_keyfile (sealed_key_bytes, -- sealed_key_size, -- &sealed_key); -+ err = grub_tpm2_protector_unmarshal_keyfile (sealed_key_bytes, -+ sealed_key_size, -+ &sealed_key); - if (err) - { - grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " --- -2.35.3 - diff --git a/0012-protectors-Add-TPM2-Key-Protector.patch b/0012-protectors-Add-TPM2-Key-Protector.patch deleted file mode 100644 index e18bc68..0000000 --- a/0012-protectors-Add-TPM2-Key-Protector.patch +++ /dev/null @@ -1,977 +0,0 @@ -From b173db7537920ee5706e1c961fea3086ada6b6dd Mon Sep 17 00:00:00 2001 -From: Hernan Gatta -Date: Tue, 1 Feb 2022 05:02:55 -0800 -Subject: [PATCH 12/14] protectors: Add TPM2 Key Protector - -The TPM2 key protector is a module that enables the automatic retrieval of a -fully-encrypted disk's unlocking key from a TPM 2.0. - -The theory of operation is such that the module accepts various arguments, most -of which are optional and therefore possess reasonable defaults. One of these -arguments is the keyfile parameter, which is mandatory. - -The value of this parameter must be a path to a sealed key file (e.g., -(hd0,gpt1)/boot/grub2/sealed_key). This sealed key file is created via the -grub-protect tool. The tool utilizes the TPM's sealing functionality to seal -(i.e., encrypt) an unlocking key using a Storage Root Key (SRK) to the values of -various Platform Configuration Registers (PCRs). These PCRs reflect the state of -the system as it boots. If the values are as expected, the system may be -considered trustworthy, at which point the TPM allows for a caller to utilize -the private component of the SRK to unseal (i.e., decrypt) the sealed key file. -The caller, in this case, is this key protector. - -The TPM2 key protector registers two commands: - -- tpm2_key_protector_init: Initializes the state of the TPM2 key protector for - later usage, clearing any previous state, too, if - any. - -- tpm2_key_protector_clear: Clears any state set by tpm2_key_protector_init. - -The way this is expected to be used requires the user to, either interactively -or, normally, via a boot script, initialize (i.e., configure) the key protector -and then specify that it be used by the cryptomount command (modifications to -this command are in a different patch). - -For instance: - -tpm2_key_protector_init --keyfile=KEYFILE1 -cryptomount DISK1 -k tpm2 - -tpm2_key_protector_init --keyfile=KEYFILE2 --pcrs=7,11 -cryptomount DISK2 -k tpm2 - -If a user does not initialize the key protector and attempts to use it anyway, -the protector returns an error. - -Signed-off-by: Hernan Gatta ---- - grub-core/Makefile.core.def | 10 + - grub-core/tpm2/args.c | 129 ++++++ - grub-core/tpm2/module.c | 710 ++++++++++++++++++++++++++++++ - include/grub/tpm2/internal/args.h | 39 ++ - 4 files changed, 888 insertions(+) - create mode 100644 grub-core/tpm2/args.c - create mode 100644 grub-core/tpm2/module.c - create mode 100644 include/grub/tpm2/internal/args.h - -diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def -index b0001a33cf..850cee2b13 100644 ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2561,6 +2561,16 @@ module = { - enable = efi; - }; - -+module = { -+ name = tpm2; -+ common = tpm2/args.c; -+ common = tpm2/buffer.c; -+ common = tpm2/module.c; -+ common = tpm2/mu.c; -+ common = tpm2/tpm2.c; -+ efi = tpm2/tcg2.c; -+}; -+ - module = { - name = tr; - common = commands/tr.c; -diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c -new file mode 100644 -index 0000000000..90c7cd8991 ---- /dev/null -+++ b/grub-core/tpm2/args.c -@@ -0,0 +1,129 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Microsoft Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+ -+grub_err_t -+grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, -+ grub_uint8_t *pcr_count) -+{ -+ char *current_pcr = value; -+ char *next_pcr; -+ unsigned long pcr; -+ grub_uint8_t i; -+ -+ if (grub_strlen (value) == 0) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ *pcr_count = 0; -+ for (i = 0; i < TPM_MAX_PCRS; i++) -+ { -+ next_pcr = grub_strchr (current_pcr, ','); -+ if (next_pcr == current_pcr) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("Empty entry in PCR list")); -+ if (next_pcr) -+ *next_pcr = '\0'; -+ -+ grub_errno = GRUB_ERR_NONE; -+ pcr = grub_strtoul (current_pcr, NULL, 10); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_error (grub_errno, -+ N_("Entry '%s' in PCR list is not a number"), -+ current_pcr); -+ -+ if (pcr > TPM_MAX_PCRS) -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Entry %lu in PCR list is too large to be a PCR " -+ "number, PCR numbers range from 0 to %u"), -+ pcr, TPM_MAX_PCRS); -+ -+ pcrs[i] = (grub_uint8_t)pcr; -+ *pcr_count += 1; -+ -+ if (!next_pcr) -+ break; -+ -+ current_pcr = next_pcr + 1; -+ if (*current_pcr == '\0') -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("Trailing comma at the end of PCR list")); -+ } -+ -+ if (i == TPM_MAX_PCRS) -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Too many PCRs in PCR list, the maximum number of " -+ "PCRs is %u"), TPM_MAX_PCRS); -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_tpm2_protector_parse_asymmetric (const char *value, TPM_ALG_ID *asymmetric) -+{ -+ if (grub_strcasecmp (value, "ECC") == 0) -+ *asymmetric = TPM_ALG_ECC; -+ else if (grub_strcasecmp (value, "RSA") == 0) -+ *asymmetric = TPM_ALG_RSA; -+ else -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Value '%s' is not a valid asymmetric key type"), -+ value); -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank) -+{ -+ if (grub_strcasecmp (value, "SHA1") == 0) -+ *bank = TPM_ALG_SHA1; -+ else if (grub_strcasecmp (value, "SHA256") == 0) -+ *bank = TPM_ALG_SHA256; -+ else if (grub_strcasecmp (value, "SHA384") == 0) -+ *bank = TPM_ALG_SHA384; -+ else -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Value '%s' is not a valid PCR bank"), value); -+ -+ return GRUB_ERR_NONE; -+} -+ -+grub_err_t -+grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle) -+{ -+ unsigned long num; -+ -+ grub_errno = GRUB_ERR_NONE; -+ num = grub_strtoul (value, NULL, 0); -+ if (grub_errno != GRUB_ERR_NONE) -+ return grub_error (grub_errno, N_("TPM handle value '%s' is not a number"), -+ value); -+ -+ if (num > GRUB_UINT_MAX) -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Value %lu is too large to be a TPM handle, TPM " -+ "handles are unsigned 32-bit integers"), num); -+ -+ *handle = (TPM_HANDLE)num; -+ -+ return GRUB_ERR_NONE; -+} -diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c -new file mode 100644 -index 0000000000..3f2f386f7e ---- /dev/null -+++ b/grub-core/tpm2/module.c -@@ -0,0 +1,710 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Microsoft Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+GRUB_MOD_LICENSE ("GPLv3+"); -+ -+typedef enum grub_tpm2_protector_mode -+{ -+ GRUB_TPM2_PROTECTOR_MODE_UNSET, -+ GRUB_TPM2_PROTECTOR_MODE_SRK, -+ GRUB_TPM2_PROTECTOR_MODE_NV -+} grub_tpm2_protector_mode_t; -+ -+struct grub_tpm2_protector_context -+{ -+ grub_tpm2_protector_mode_t mode; -+ grub_uint8_t pcrs[TPM_MAX_PCRS]; -+ grub_uint8_t pcr_count; -+ TPM_ALG_ID asymmetric; -+ TPM_ALG_ID bank; -+ const char *keyfile; -+ TPM_HANDLE srk; -+ TPM_HANDLE nv; -+}; -+ -+static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = -+ { -+ /* Options for all modes */ -+ { -+ .longarg = "mode", -+ .shortarg = 'm', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV " -+ "Index ('nv')."), -+ }, -+ { -+ .longarg = "pcrs", -+ .shortarg = 'p', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Comma-separated list of PCRs used to authorize key release " -+ "(e.g., '7,11', default is 7."), -+ }, -+ { -+ .longarg = "bank", -+ .shortarg = 'b', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Bank of PCRs used to authorize key release: " -+ "SHA1, SHA256 (default), or SHA384."), -+ }, -+ /* SRK-mode options */ -+ { -+ .longarg = "keyfile", -+ .shortarg = 'k', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Required in SRK mode, path to the sealed key file to unseal using " -+ "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key)."), -+ }, -+ { -+ .longarg = "srk", -+ .shortarg = 's', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("In SRK mode, the SRK handle if the SRK is persistent " -+ "(default is 0x81000001)."), -+ }, -+ { -+ .longarg = "asymmetric", -+ .shortarg = 'a', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("In SRK mode, the type of SRK: RSA (default) or ECC."), -+ }, -+ /* NV Index-mode options */ -+ { -+ .longarg = "nvindex", -+ .shortarg = 'n', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Required in NV Index mode, the NV handle to read which must " -+ "readily exist on the TPM and which contains the key."), -+ }, -+ /* End of list */ -+ {0, 0, 0, 0, 0, 0} -+ }; -+ -+static grub_extcmd_t grub_tpm2_protector_init_cmd; -+static grub_extcmd_t grub_tpm2_protector_clear_cmd; -+static struct grub_tpm2_protector_context grub_tpm2_protector_ctx = { 0 }; -+ -+static grub_err_t -+grub_tpm2_protector_srk_read_keyfile (const char *filepath, void **buffer, -+ grub_size_t *buffer_size) -+{ -+ grub_file_t sealed_key_file; -+ grub_off_t sealed_key_size; -+ void *sealed_key_buffer; -+ grub_off_t sealed_key_read; -+ -+ sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE); -+ if (!sealed_key_file) -+ { -+ grub_dprintf ("tpm2", "Could not open sealed key file.\n"); -+ /* grub_file_open sets grub_errno on error, and if we do no unset it, -+ * future calls to grub_file_open will fail (and so will anybody up the -+ * stack who checks the value, if any). */ -+ grub_errno = GRUB_ERR_NONE; -+ return GRUB_ERR_FILE_NOT_FOUND; -+ } -+ -+ sealed_key_size = grub_file_size (sealed_key_file); -+ if (!sealed_key_size) -+ { -+ grub_dprintf ("tpm2", "Could not read sealed key file size.\n"); -+ grub_file_close (sealed_key_file); -+ return GRUB_ERR_OUT_OF_RANGE; -+ } -+ -+ sealed_key_buffer = grub_malloc (sealed_key_size); -+ if (!sealed_key_buffer) -+ { -+ grub_dprintf ("tpm2", "Could not allocate buffer for sealed key.\n"); -+ grub_file_close (sealed_key_file); -+ return GRUB_ERR_OUT_OF_MEMORY; -+ } -+ -+ sealed_key_read = grub_file_read (sealed_key_file, sealed_key_buffer, -+ sealed_key_size); -+ if (sealed_key_read != sealed_key_size) -+ { -+ grub_dprintf ("tpm2", "Could not retrieve sealed key file contents.\n"); -+ grub_free (sealed_key_buffer); -+ grub_file_close (sealed_key_file); -+ return GRUB_ERR_FILE_READ_ERROR; -+ } -+ -+ grub_file_close (sealed_key_file); -+ -+ *buffer = sealed_key_buffer; -+ *buffer_size = sealed_key_size; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_srk_unmarshal_keyfile (void *sealed_key, -+ grub_size_t sealed_key_size, -+ TPM2_SEALED_KEY *sk) -+{ -+ struct grub_tpm2_buffer buf; -+ -+ grub_tpm2_buffer_init (&buf); -+ if (sealed_key_size > buf.cap) -+ { -+ grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer " -+ "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ grub_memcpy (buf.data, sealed_key, sealed_key_size); -+ buf.size = sealed_key_size; -+ -+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); -+ grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private); -+ -+ if (buf.error) -+ { -+ grub_dprintf ("tpm2", "Could not unmarshal sealed key file, it is likely " -+ "malformed.\n"); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_srk_get (const struct grub_tpm2_protector_context *ctx, -+ TPM_HANDLE *srk) -+{ -+ TPM_RC rc; -+ TPM2B_PUBLIC public; -+ TPMS_AUTH_COMMAND authCommand = { 0 }; -+ TPM2B_SENSITIVE_CREATE inSensitive = { 0 }; -+ TPM2B_PUBLIC inPublic = { 0 }; -+ TPM2B_DATA outsideInfo = { 0 }; -+ TPML_PCR_SELECTION creationPcr = { 0 }; -+ TPM2B_PUBLIC outPublic = { 0 }; -+ TPM2B_CREATION_DATA creationData = { 0 }; -+ TPM2B_DIGEST creationHash = { 0 }; -+ TPMT_TK_CREATION creationTicket = { 0 }; -+ TPM2B_NAME srkName = { 0 }; -+ TPM_HANDLE srkHandle; -+ -+ /* Find SRK */ -+ rc = TPM2_ReadPublic (ctx->srk, NULL, &public); -+ if (rc == TPM_RC_SUCCESS) -+ { -+ *srk = ctx->srk; -+ return GRUB_ERR_NONE; -+ } -+ -+ /* The handle exists but its public area could not be read. */ -+ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE) -+ { -+ grub_dprintf ("tpm2", "The SRK handle (0x%x) exists on the TPM but its " -+ "public area could not be read (TPM2_ReadPublic " -+ "failed with TSS/TPM error %u).\n", ctx->srk, rc); -+ return GRUB_ERR_BAD_DEVICE; -+ } -+ -+ /* Create SRK */ -+ authCommand.sessionHandle = TPM_RS_PW; -+ inPublic.publicArea.type = ctx->asymmetric; -+ inPublic.publicArea.nameAlg = TPM_ALG_SHA256; -+ inPublic.publicArea.objectAttributes.restricted = 1; -+ inPublic.publicArea.objectAttributes.userWithAuth = 1; -+ inPublic.publicArea.objectAttributes.decrypt = 1; -+ inPublic.publicArea.objectAttributes.fixedTPM = 1; -+ inPublic.publicArea.objectAttributes.fixedParent = 1; -+ inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; -+ inPublic.publicArea.objectAttributes.noDA = 1; -+ -+ if (ctx->asymmetric == TPM_ALG_RSA) -+ { -+ inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES; -+ inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; -+ inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB; -+ inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; -+ inPublic.publicArea.parameters.rsaDetail.keyBits = 2048; -+ inPublic.publicArea.parameters.rsaDetail.exponent = 0; -+ } -+ else if (ctx->asymmetric == TPM_ALG_ECC) -+ { -+ inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES; -+ inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; -+ inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB; -+ inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; -+ inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256; -+ inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; -+ } -+ else -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ rc = TPM2_CreatePrimary (TPM_RH_OWNER, &authCommand, &inSensitive, &inPublic, -+ &outsideInfo, &creationPcr, &srkHandle, &outPublic, -+ &creationData, &creationHash, &creationTicket, -+ &srkName, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ grub_dprintf ("tpm2", "Could not create SRK (TPM2_CreatePrimary failed " -+ "with TSS/TPM error %u).\n", rc); -+ return GRUB_ERR_BAD_DEVICE; -+ } -+ -+ *srk = srkHandle; -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, -+ grub_uint8_t **key, grub_size_t *key_size) -+{ -+ TPM_RC rc; -+ TPM2_SEALED_KEY sealed_key; -+ void *sealed_key_bytes; -+ grub_size_t sealed_key_size; -+ TPM_HANDLE srk_handle; -+ TPM2B_NONCE nonceCaller = { 0 }; -+ TPM2B_ENCRYPTED_SECRET salt = { 0 }; -+ TPMT_SYM_DEF symmetric = { 0 }; -+ TPM2B_NONCE nonceTPM = { 0 }; -+ TPMI_SH_AUTH_SESSION session; -+ TPML_PCR_SELECTION pcrSel = { -+ .count = 1, -+ .pcrSelections = { -+ { -+ .hash = ctx->bank, -+ .sizeOfSelect = 3, -+ .pcrSelect = { 0 } -+ }, -+ } -+ }; -+ TPMS_AUTH_COMMAND authCmd = { 0 }; -+ TPM_HANDLE sealed_key_handle; -+ TPM2B_NAME name; -+ TPMS_AUTH_RESPONSE authResponse; -+ TPM2B_SENSITIVE_DATA data; -+ grub_uint8_t *key_out; -+ grub_uint8_t i; -+ grub_err_t err; -+ -+ /* Retrieve Sealed Key */ -+ err = grub_tpm2_protector_srk_read_keyfile (ctx->keyfile, &sealed_key_bytes, -+ &sealed_key_size); -+ if (err) -+ return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile); -+ -+ err = grub_tpm2_protector_srk_unmarshal_keyfile (sealed_key_bytes, -+ sealed_key_size, -+ &sealed_key); -+ if (err) -+ { -+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " -+ "TPM wire format")); -+ goto exit1; -+ } -+ -+ /* Get SRK */ -+ err = grub_tpm2_protector_srk_get (ctx, &srk_handle); -+ if (err) -+ { -+ grub_error (err, N_("Failed to retrieve the SRK")); -+ goto exit1; -+ } -+ -+ err = GRUB_ERR_BAD_DEVICE; -+ -+ /* Start Auth Session */ -+ nonceCaller.size = TPM_SHA256_DIGEST_SIZE; -+ symmetric.algorithm = TPM_ALG_NULL; -+ -+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonceCaller, &salt, -+ TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, -+ &session, &nonceTPM, 0); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession " -+ "failed with TSS/TPM error %u)"), rc); -+ goto exit2; -+ } -+ -+ /* Policy PCR */ -+ for (i = 0; i < ctx->pcr_count; i++) -+ pcrSel -+ .pcrSelections[0] -+ .pcrSelect[TPM2_PCR_TO_SELECT(ctx->pcrs[i])] -+ |= TPM2_PCR_TO_BIT(ctx->pcrs[i]); -+ -+ rc = TPM2_PolicyPCR (session, NULL, NULL, &pcrSel, NULL); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed " -+ "with TSS/TPM error %u)"), rc); -+ goto exit3; -+ } -+ -+ /* Load Sealed Key */ -+ authCmd.sessionHandle = TPM_RS_PW; -+ rc = TPM2_Load (srk_handle, &authCmd, &sealed_key.private, &sealed_key.public, -+ &sealed_key_handle, &name, &authResponse); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to load sealed key (TPM2_Load failed with " -+ "TSS/TPM error %u)"), rc); -+ goto exit3; -+ } -+ -+ /* Unseal Sealed Key */ -+ authCmd.sessionHandle = session; -+ grub_memset (&authResponse, 0, sizeof (authResponse)); -+ -+ rc = TPM2_Unseal (sealed_key_handle, &authCmd, &data, &authResponse); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed " -+ "with TSS/TPM error %u)"), rc); -+ goto exit4; -+ } -+ -+ /* Epilogue */ -+ key_out = grub_malloc (data.size); -+ if (!key_out) -+ { -+ err = GRUB_ERR_OUT_OF_MEMORY; -+ grub_error (err, N_("No memory left to allocate unlock key buffer")); -+ goto exit4; -+ } -+ -+ grub_memcpy (key_out, data.buffer, data.size); -+ -+ *key = key_out; -+ *key_size = data.size; -+ -+ err = GRUB_ERR_NONE; -+ -+exit4: -+ TPM2_FlushContext (sealed_key_handle); -+ -+exit3: -+ TPM2_FlushContext (session); -+ -+exit2: -+ TPM2_FlushContext (srk_handle); -+ -+exit1: -+ grub_free (sealed_key_bytes); -+ return err; -+} -+ -+static grub_err_t -+grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx, -+ grub_uint8_t **key, grub_size_t *key_size) -+{ -+ (void)ctx; -+ (void)key; -+ (void)key_size; -+ -+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, -+ N_("NV Index mode is not implemented yet")); -+} -+ -+static grub_err_t -+grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx, -+ grub_uint8_t **key, grub_size_t *key_size) -+{ -+ switch (ctx->mode) -+ { -+ case GRUB_TPM2_PROTECTOR_MODE_SRK: -+ return grub_tpm2_protector_srk_recover (ctx, key, key_size); -+ case GRUB_TPM2_PROTECTOR_MODE_NV: -+ return grub_tpm2_protector_nv_recover (ctx, key, key_size); -+ default: -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+} -+ -+static grub_err_t -+grub_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size) -+{ -+ grub_err_t err; -+ -+ /* Expect a call to tpm2_protector_init before anybody tries to use us */ -+ if (grub_tpm2_protector_ctx.mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) -+ return grub_error (GRUB_ERR_INVALID_COMMAND, -+ N_("Cannot use TPM2 key protector without initializing " -+ "it, call tpm2_protector_init first")); -+ -+ if (!key) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ err = grub_tpm2_protector_recover (&grub_tpm2_protector_ctx, key, key_size); -+ if (err) -+ return err; -+ -+ return GRUB_ERR_NONE; -+} -+ -+ -+static grub_err_t -+grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) -+{ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) -+ ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK; -+ -+ /* Checks for SRK mode */ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && !ctx->keyfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In SRK mode, a key file must be specified: " -+ "--keyfile or -k")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->nv) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In SRK mode, an NV Index cannot be specified")); -+ -+ /* Checks for NV mode */ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && !ctx->nv) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, an NV Index must be specified: " -+ "--nvindex or -n")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->keyfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, a keyfile cannot be specified")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->srk) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, an SRK cannot be specified")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->asymmetric) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, an asymmetric key type cannot be " -+ "specified")); -+ -+ /* Defaults assignment */ -+ if (!ctx->bank) -+ ctx->bank = TPM_ALG_SHA256; -+ -+ if (!ctx->pcr_count) -+ { -+ ctx->pcrs[0] = 7; -+ ctx->pcr_count = 1; -+ } -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK) -+ { -+ if (!ctx->srk) -+ ctx->srk = TPM2_SRK_HANDLE; -+ -+ if (!ctx->asymmetric) -+ ctx->asymmetric = TPM_ALG_RSA; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) -+{ -+ if (grub_strlen (value) == 0) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ *keyfile = grub_strdup (value); -+ if (!*keyfile) -+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, -+ N_("No memory to duplicate keyfile path")); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_parse_mode (const char *value, -+ grub_tpm2_protector_mode_t *mode) -+{ -+ if (grub_strcmp (value, "srk") == 0) -+ *mode = GRUB_TPM2_PROTECTOR_MODE_SRK; -+ else if (grub_strcmp (value, "nv") == 0) -+ *mode = GRUB_TPM2_PROTECTOR_MODE_NV; -+ else -+ return grub_error (GRUB_ERR_OUT_OF_RANGE, -+ N_("Value '%s' is not a valid TPM2 key protector mode"), -+ value); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc, -+ char **args __attribute__ ((unused))) -+{ -+ struct grub_arg_list *state = ctxt->state; -+ grub_err_t err; -+ -+ if (argc) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("The TPM2 key protector does not accept any " -+ "non-option arguments (i.e., like -o and/or --option " -+ "only)")); -+ -+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); -+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); -+ -+ if (state[0].set) /* mode */ -+ { -+ err = grub_tpm2_protector_parse_mode (state[0].arg, -+ &grub_tpm2_protector_ctx.mode); -+ if (err) -+ return err; -+ } -+ -+ if (state[1].set) /* pcrs */ -+ { -+ err = grub_tpm2_protector_parse_pcrs (state[1].arg, -+ grub_tpm2_protector_ctx.pcrs, -+ &grub_tpm2_protector_ctx.pcr_count); -+ if (err) -+ return err; -+ } -+ -+ if (state[2].set) /* bank */ -+ { -+ err = grub_tpm2_protector_parse_bank (state[2].arg, -+ &grub_tpm2_protector_ctx.bank); -+ if (err) -+ return err; -+ } -+ -+ if (state[3].set) /* keyfile */ -+ { -+ err = grub_tpm2_protector_parse_keyfile (state[3].arg, -+ &grub_tpm2_protector_ctx.keyfile); -+ if (err) -+ return err; -+ } -+ -+ if (state[4].set) /* srk */ -+ { -+ err = grub_tpm2_protector_parse_tpm_handle (state[4].arg, -+ &grub_tpm2_protector_ctx.srk); -+ if (err) -+ return err; -+ } -+ -+ if (state[5].set) /* asymmetric */ -+ { -+ err = grub_tpm2_protector_parse_asymmetric (state[5].arg, -+ &grub_tpm2_protector_ctx.asymmetric); -+ if (err) -+ return err; -+ } -+ -+ if (state[6].set) /* nvindex */ -+ { -+ err = grub_tpm2_protector_parse_tpm_handle (state[6].arg, -+ &grub_tpm2_protector_ctx.nv); -+ if (err) -+ return err; -+ } -+ -+ err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); -+ -+ /* This command only initializes the protector, so nothing else to do. */ -+ -+ return err; -+} -+ -+static grub_err_t -+grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ ((unused)), -+ int argc, -+ char **args __attribute__ ((unused))) -+{ -+ if (argc) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("tpm2_key_protector_clear accepts no arguments")); -+ -+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); -+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); -+ -+ return GRUB_ERR_NONE; -+} -+ -+static struct grub_key_protector grub_tpm2_key_protector = -+ { -+ .name = "tpm2", -+ .recover_key = grub_tpm2_protector_recover_key -+ }; -+ -+GRUB_MOD_INIT (tpm2) -+{ -+ grub_tpm2_protector_init_cmd = -+ grub_register_extcmd ("tpm2_key_protector_init", -+ grub_tpm2_protector_init_cmd_handler, 0, -+ N_("[-m mode] " -+ "[-p pcr_list] " -+ "[-b pcr_bank] " -+ "[-k sealed_key_file_path] " -+ "[-s srk_handle] " -+ "[-a asymmetric_key_type] " -+ "[-n nv_index]"), -+ N_("Initialize the TPM2 key protector."), -+ grub_tpm2_protector_init_cmd_options); -+ grub_tpm2_protector_clear_cmd = -+ grub_register_extcmd ("tpm2_key_protector_clear", -+ grub_tpm2_protector_clear_cmd_handler, 0, NULL, -+ N_("Clear the TPM2 key protector if previously initialized."), -+ NULL); -+ grub_key_protector_register (&grub_tpm2_key_protector); -+} -+ -+GRUB_MOD_FINI (tpm2) -+{ -+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile); -+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); -+ -+ grub_key_protector_unregister (&grub_tpm2_key_protector); -+ grub_unregister_extcmd (grub_tpm2_protector_clear_cmd); -+ grub_unregister_extcmd (grub_tpm2_protector_init_cmd); -+} -diff --git a/include/grub/tpm2/internal/args.h b/include/grub/tpm2/internal/args.h -new file mode 100644 -index 0000000000..6341fce1c5 ---- /dev/null -+++ b/include/grub/tpm2/internal/args.h -@@ -0,0 +1,39 @@ -+/* -+ * GRUB -- GRand Unified Bootloader -+ * Copyright (C) 2022 Microsoft Corporation -+ * -+ * GRUB is free software: you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation, either version 3 of the License, or -+ * (at your option) any later version. -+ * -+ * GRUB is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with GRUB. If not, see . -+ */ -+ -+#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER -+#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1 -+ -+#include -+#include -+ -+grub_err_t -+grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, -+ grub_uint8_t *pcr_count); -+ -+grub_err_t -+grub_tpm2_protector_parse_asymmetric (const char *value, -+ TPM_ALG_ID *asymmetric); -+ -+grub_err_t -+grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank); -+ -+grub_err_t -+grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle); -+ -+#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */ --- -2.34.1 - diff --git a/0012-tpm2-initialize-the-PCR-selection-list-early.patch b/0012-tpm2-initialize-the-PCR-selection-list-early.patch deleted file mode 100644 index dd96678..0000000 --- a/0012-tpm2-initialize-the-PCR-selection-list-early.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 1dcae21faa281496a79ee2caf59772bf36b16b9e Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 8 Feb 2023 11:20:45 +0800 -Subject: [PATCH 12/13] tpm2: initialize the PCR selection list early - -The PCR selection list will be used in several TPM2 commands for the -authorized policy mode. Declare the PCR selection list in -grub_tpm2_protector_context and initialize the list after checking the -arguments of the tpm2 module so that other functions can use the list -directly. - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/module.c | 39 +++++++++++++++++++++------------------ - 1 file changed, 21 insertions(+), 18 deletions(-) - -diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c -index b404d8449..c819ef616 100644 ---- a/grub-core/tpm2/module.c -+++ b/grub-core/tpm2/module.c -@@ -43,6 +43,7 @@ struct grub_tpm2_protector_context - grub_tpm2_protector_mode_t mode; - grub_uint8_t pcrs[TPM_MAX_PCRS]; - grub_uint8_t pcr_count; -+ TPML_PCR_SELECTION pcr_list; - TPM_ALG_ID asymmetric; - TPM_ALG_ID bank; - const char *keyfile; -@@ -353,23 +354,12 @@ grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - TPM2B_NONCE nonceCaller = { 0 }; - TPMT_SYM_DEF symmetric = { 0 }; - TPMI_SH_AUTH_SESSION session; -- TPML_PCR_SELECTION pcrSel = { -- .count = 1, -- .pcrSelections = { -- { -- .hash = ctx->bank, -- .sizeOfSelect = 3, -- .pcrSelect = { 0 } -- }, -- } -- }; - TPMS_AUTH_COMMAND authCmd = { 0 }; - TPM_HANDLE sealed_key_handle; - TPM2B_NAME name; - TPMS_AUTH_RESPONSE authResponse; - TPM2B_SENSITIVE_DATA data; - grub_uint8_t *key_out; -- grub_uint8_t i; - grub_err_t err; - - /* Retrieve Sealed Key */ -@@ -413,13 +403,7 @@ grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - } - - /* Policy PCR */ -- for (i = 0; i < ctx->pcr_count; i++) -- pcrSel -- .pcrSelections[0] -- .pcrSelect[TPM2_PCR_TO_SELECT(ctx->pcrs[i])] -- |= TPM2_PCR_TO_BIT(ctx->pcrs[i]); -- -- rc = TPM2_PolicyPCR (session, NULL, NULL, &pcrSel, NULL); -+ rc = TPM2_PolicyPCR (session, NULL, NULL, &ctx->pcr_list, NULL); - if (rc) - { - grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed " -@@ -538,6 +522,23 @@ grub_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size) - return GRUB_ERR_NONE; - } - -+static void -+initialize_pcr_list (struct grub_tpm2_protector_context *ctx) -+{ -+ TPMS_PCR_SELECTION *pcr_sel; -+ grub_uint8_t i; -+ -+ grub_memset (&ctx->pcr_list, 0, sizeof (TPML_PCR_SELECTION)); -+ -+ ctx->pcr_list.count = 1; -+ -+ pcr_sel = &ctx->pcr_list.pcrSelections[0]; -+ pcr_sel->hash = ctx->bank; -+ pcr_sel->sizeOfSelect = 3; -+ -+ for (i = 0; i < ctx->pcr_count; i++) -+ pcr_sel->pcrSelect[TPM2_PCR_TO_SELECT(ctx->pcrs[i])] |= TPM2_PCR_TO_BIT(ctx->pcrs[i]); -+} - - static grub_err_t - grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) -@@ -593,6 +594,8 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) - ctx->asymmetric = TPM_ALG_RSA; - } - -+ initialize_pcr_list (ctx); -+ - return GRUB_ERR_NONE; - } - --- -2.35.3 - diff --git a/0013-tpm2-support-unsealing-key-with-authorized-policy.patch b/0013-tpm2-support-unsealing-key-with-authorized-policy.patch deleted file mode 100644 index d638979..0000000 --- a/0013-tpm2-support-unsealing-key-with-authorized-policy.patch +++ /dev/null @@ -1,794 +0,0 @@ -From 47220d1ce8fffac3654454b8a981385133b7c23a Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 8 Feb 2023 11:26:25 +0800 -Subject: [PATCH 13/13] tpm2: support unsealing key with authorized policy - -To solve the PCR brittleness, TPM 2.0 allows the administrator to -'authorize' a new PCR policy, i.e. a new set of PCR values, to unseal -the existing key. This commit extends the SRK mode to support the -authorized policy mode to unseal the disk encryption key. - -The usage of the authorized policy mode is very similar to the SRK mode -except two additional arguments: "-P" for the publicy key and "-S" for -the signed policy. - -Example of the authorized policy mode: - -tpm2_key_protector_init -m authpol -b sha256 -p 0,2,4,7 \ - -k (hd0,gpt1)/boot/grub2/sealed.key \ - -P (hd0,gpt1)/boot/grub2/pub.key \ - -S (hd0,gpt1)/boot/grub2/pol.sig - -Signed-off-by: Gary Lin ---- - grub-core/tpm2/module.c | 614 +++++++++++++++++++++++++++++++++++++++- - 1 file changed, 602 insertions(+), 12 deletions(-) - -diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c -index c819ef616..8e1b14146 100644 ---- a/grub-core/tpm2/module.c -+++ b/grub-core/tpm2/module.c -@@ -35,7 +35,8 @@ typedef enum grub_tpm2_protector_mode - { - GRUB_TPM2_PROTECTOR_MODE_UNSET, - GRUB_TPM2_PROTECTOR_MODE_SRK, -- GRUB_TPM2_PROTECTOR_MODE_NV -+ GRUB_TPM2_PROTECTOR_MODE_NV, -+ GRUB_TPM2_PROTECTOR_MODE_AUTHPOL - } grub_tpm2_protector_mode_t; - - struct grub_tpm2_protector_context -@@ -47,6 +48,8 @@ struct grub_tpm2_protector_context - TPM_ALG_ID asymmetric; - TPM_ALG_ID bank; - const char *keyfile; -+ const char *pkfile; -+ const char *sigfile; - TPM_HANDLE srk; - TPM_HANDLE nv; - const char *efivar; -@@ -62,8 +65,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - .arg = NULL, - .type = ARG_TYPE_STRING, - .doc = -- N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV " -- "Index ('nv')."), -+ N_("Unseal key using SRK ('srk') (default), retrieve it from an NV " -+ "Index ('nv'), or unseal key with a authorized policy ('authpol')."), - }, - { - .longarg = "pcrs", -@@ -85,7 +88,7 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - N_("Bank of PCRs used to authorize key release: " - "SHA1, SHA256 (default), or SHA384."), - }, -- /* SRK-mode options */ -+ /* SRK-mode and Authorized Policy-mode options */ - { - .longarg = "keyfile", - .shortarg = 'k', -@@ -93,8 +96,9 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - .arg = NULL, - .type = ARG_TYPE_STRING, - .doc = -- N_("Required in SRK mode, path to the sealed key file to unseal using " -- "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key)."), -+ N_("Required in SRK and Authorized Policy mode, path to the sealed " -+ "key file to unseal using the TPM " -+ "(e.g., (hd0,gpt1)/boot/grub2/sealed_key)."), - }, - { - .longarg = "srk", -@@ -103,8 +107,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - .arg = NULL, - .type = ARG_TYPE_STRING, - .doc = -- N_("In SRK mode, the SRK handle if the SRK is persistent " -- "(default is 0x81000001)."), -+ N_("In SRK and Authorized Policy mode, the SRK handle if the SRK is " -+ "persistent (default is 0x81000001)."), - }, - { - .longarg = "asymmetric", -@@ -113,7 +117,8 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - .arg = NULL, - .type = ARG_TYPE_STRING, - .doc = -- N_("In SRK mode, the type of SRK: RSA (default) or ECC."), -+ N_("In SRK and Authorized Policy mode, the type of SRK: RSA " -+ "(default) or ECC."), - }, - /* NV Index-mode options */ - { -@@ -136,6 +141,26 @@ static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = - .doc = - N_("Publish the unsealed key to the indicated UEFI variable."), - }, -+ /* Authorized Policy-mode options */ -+ { -+ .longarg = "pkfile", -+ .shortarg = 'P', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Public key file to verify the PCR policy signature" -+ "(e.g., (hd0,gpt1)/boot/grub2/pub.key)"), -+ }, -+ { -+ .longarg = "sigfile", -+ .shortarg = 'S', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("PCR policy signature file (e.g., (hd0,gpt1)/boot/grub2/pol.sig)"), -+ }, - /* End of list */ - {0, 0, 0, 0, 0, 0} - }; -@@ -199,6 +224,66 @@ grub_tpm2_protector_read_file (const char *filepath, void **buffer, - return GRUB_ERR_NONE; - } - -+static grub_err_t -+grub_tpm2_protector_unmarshal_pkfile (void *pub_key, -+ grub_size_t pub_key_size, -+ TPM2B_PUBLIC *pk) -+{ -+ struct grub_tpm2_buffer buf; -+ -+ grub_tpm2_buffer_init (&buf); -+ if (pub_key_size > buf.cap) -+ { -+ grub_dprintf ("tpm2", "Public key file is larger than decode buffer " -+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", pub_key_size, buf.cap); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ grub_memcpy (buf.data, pub_key, pub_key_size); -+ buf.size = pub_key_size; -+ -+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, pk); -+ -+ if (buf.error) -+ { -+ grub_dprintf ("tpm2", "Could not unmarshal public key file, it is likely " -+ "malformed.\n"); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ -+static grub_err_t -+grub_tpm2_protector_unmarshal_sigfile (void *sig, -+ grub_size_t sig_size, -+ TPMT_SIGNATURE *signature) -+{ -+ struct grub_tpm2_buffer buf; -+ -+ grub_tpm2_buffer_init (&buf); -+ if (sig_size > buf.cap) -+ { -+ grub_dprintf ("tpm2", "Signed PCR policy file is larger than decode buffer " -+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", sig_size, buf.cap); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ grub_memcpy (buf.data, sig, sig_size); -+ buf.size = sig_size; -+ -+ grub_tpm2_mu_TPMT_SIGNATURE_Unmarshal (&buf, signature); -+ -+ if (buf.error) -+ { -+ grub_dprintf ("tpm2", "Could not unmarshal public key file, it is likely " -+ "malformed.\n"); -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ return GRUB_ERR_NONE; -+} -+ - static grub_err_t - grub_tpm2_protector_unmarshal_keyfile (void *sealed_key, - grub_size_t sealed_key_size, -@@ -486,6 +571,433 @@ grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx, - N_("NV Index mode is not implemented yet")); - } - -+static grub_err_t -+get_pcr_digest (const struct grub_tpm2_protector_context *ctx, -+ TPM2B_DIGEST *pcr_digest) -+{ -+ TPM_RC rc; -+ TPML_PCR_SELECTION pcr_list_out = { 0 }; -+ TPML_DIGEST pcr_values = { 0 }; -+ grub_size_t pcr_digest_len; -+ TPM2B_AUTH auth = { 0 }; -+ TPMI_DH_OBJECT sequence = 0; -+ TPMS_AUTH_COMMAND authCmd; -+ grub_uint8_t i; -+ TPM2B_DIGEST result_digest; -+ grub_err_t err = GRUB_ERR_INVALID_COMMAND; -+ -+ if (!pcr_digest) -+ return GRUB_ERR_BAD_ARGUMENT; -+ -+ /* PCR Read */ -+ rc = TPM2_PCR_Read (NULL, &ctx->pcr_list, NULL, &pcr_list_out, &pcr_values, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ return grub_error (err, N_("Failed to read PCRs (TPM error: 0x%x)."), rc); -+ } -+ -+ if ((pcr_list_out.count != ctx->pcr_list.count) || -+ (ctx->pcr_list.pcrSelections[0].sizeOfSelect != -+ pcr_list_out.pcrSelections[0].sizeOfSelect)) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ return grub_error (err, N_("Could not read all the specified PCRs.")); -+ } -+ -+ /* Check the hash algorithm */ -+ switch (ctx->bank) -+ { -+ case TPM_ALG_SHA1: -+ pcr_digest_len = TPM_SHA1_DIGEST_SIZE; -+ break; -+ case TPM_ALG_SHA256: -+ pcr_digest_len = TPM_SHA256_DIGEST_SIZE; -+ break; -+ case TPM_ALG_SHA384: -+ pcr_digest_len = TPM_SHA384_DIGEST_SIZE; -+ break; -+ case TPM_ALG_SHA512: -+ pcr_digest_len = TPM_SHA512_DIGEST_SIZE; -+ break; -+ default: -+ return GRUB_ERR_BAD_ARGUMENT; -+ } -+ -+ /* Start the hash sequence with an empty password (auth) */ -+ rc = TPM2_HashSequenceStart (NULL, &auth, ctx->bank, &sequence, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ return grub_error (err, -+ N_("Failed to start hash sequence (TPM error: 0x%x)."), -+ rc); -+ } -+ -+ /* Set up the password session with an empty password for TPM2_SequenceUpdate */ -+ /* and TPM2_SequenceComplete */ -+ grub_memset (&authCmd, 0, sizeof (TPMS_AUTH_COMMAND)); -+ authCmd.sessionHandle = TPM_RS_PW; -+ -+ for (i = 0; i < ctx->pcr_count; i++) -+ { -+ if (pcr_values.digests[i].size != pcr_digest_len) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, -+ N_("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but got %u bytes.\n"), -+ pcr_digest_len, pcr_values.digests[i].size); -+ goto error; -+ } -+ -+ rc = TPM2_SequenceUpdate (sequence, &authCmd, -+ (TPM2B_MAX_BUFFER *)&pcr_values.digests[i], -+ NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, -+ N_("Failed to update hash sequence (TPM error: 0x%x)."), -+ rc); -+ goto error; -+ } -+ } -+ -+ rc = TPM2_SequenceComplete (sequence, &authCmd, NULL, TPM_RH_NULL, -+ &result_digest, NULL, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, -+ N_("Failed to complete hash sequence (TPM error: 0x%x)."), -+ rc); -+ goto error; -+ } -+ -+ *pcr_digest = result_digest; -+ sequence = 0; -+ err = GRUB_ERR_NONE; -+ -+error: -+ -+ /* End the sequence if necessary */ -+ if (sequence != 0) -+ { -+ grub_memset (&authCmd, 0, sizeof (TPMS_AUTH_COMMAND)); -+ authCmd.sessionHandle = TPM_RS_PW; -+ TPM2_SequenceComplete (sequence, &authCmd, NULL, TPM_RH_NULL, -+ &result_digest, NULL, NULL); -+ } -+ -+ return err; -+} -+ -+static grub_err_t -+grub_tpm2_protector_authpol_digest (const struct grub_tpm2_protector_context *ctx, -+ TPM2B_DIGEST *digest) -+{ -+ TPM_RC rc; -+ TPM2B_DIGEST pcr_digest; -+ TPM2B_NONCE nonce = { 0 }; -+ TPMT_SYM_DEF symmetric = { 0 }; -+ TPMI_SH_AUTH_SESSION session = 0; -+ TPM2B_DIGEST policy_digest = { 0 }; -+ grub_err_t err; -+ -+ err = get_pcr_digest (ctx, &pcr_digest); -+ if (err != GRUB_ERR_NONE) -+ return err; -+ -+ /* Start Trial Session to calculate the policy digest */ -+ nonce.size = TPM_SHA256_DIGEST_SIZE; -+ symmetric.algorithm = TPM_ALG_NULL; -+ -+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonce, NULL, -+ TPM_SE_TRIAL, &symmetric, TPM_ALG_SHA256, -+ &session, NULL, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, -+ N_("Failed to start trial policy session (TPM error: 0x%x)."), -+ rc); -+ goto error; -+ } -+ -+ /* PCR Policy */ -+ rc = TPM2_PolicyPCR (session, NULL, &pcr_digest, &ctx->pcr_list, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, _("Failed to submit PCR policy (TPM error: 0x%x)."), -+ rc); -+ goto error; -+ } -+ -+ /* Retrieve Policy Digest */ -+ rc = TPM2_PolicyGetDigest (session, NULL, &policy_digest, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, _("Failed to get policy digest (TPM error: 0x%x)."), -+ rc); -+ goto error; -+ } -+ -+ /* Epilogue */ -+ *digest = policy_digest; -+ err = GRUB_ERR_NONE; -+ -+error: -+ TPM2_FlushContext (session); -+ -+ return err; -+} -+ -+static grub_err_t -+grub_tpm2_protector_authpol_recover (const struct grub_tpm2_protector_context *ctx, -+ grub_uint8_t **key, grub_size_t *key_size) -+{ -+ TPM_RC rc; -+ TPM2B_DIGEST pcr_policy; -+ TPM2B_DIGEST pcr_policy_hash; -+ TPM2B_PUBLIC pub_key; -+ void *pub_key_bytes = NULL; -+ grub_size_t pub_key_size; -+ TPM2B_NAME pubname; -+ TPMT_SIGNATURE signature; -+ void *sig_bytes = NULL; -+ grub_size_t sig_size; -+ TPM2_SEALED_KEY sealed_key; -+ void *sealed_key_bytes = NULL; -+ grub_size_t sealed_key_size; -+ TPM_HANDLE pubkey_handle = 0; -+ TPM_HANDLE primary_handle = 0; -+ TPM_HANDLE sealed_key_handle = 0; -+ TPMT_SYM_DEF symmetric = { 0 }; -+ TPM2B_NONCE nonceCaller = { 0 }; -+ TPMI_SH_AUTH_SESSION session; -+ TPM2B_SENSITIVE_DATA data; -+ TPMS_AUTH_COMMAND authCmd = { 0 }; -+ TPMT_TK_VERIFIED verification_ticket; -+ grub_uint8_t *key_out; -+ grub_err_t err; -+ -+ /* Retrieve Public Key */ -+ err = grub_tpm2_protector_read_file (ctx->pkfile, &pub_key_bytes, -+ &pub_key_size); -+ if (err) -+ return grub_error (err, N_("Failed to read public key file %s"), -+ ctx->pkfile); -+ -+ err = grub_tpm2_protector_unmarshal_pkfile (pub_key_bytes, -+ pub_key_size, -+ &pub_key); -+ if (err) -+ { -+ grub_error (err, N_("Failed to unmarshal public key, ensure the public " -+ "key file is in TPM wire format")); -+ goto exit1; -+ } -+ -+ /* Retrieve Signed PCR Policy */ -+ err = grub_tpm2_protector_read_file (ctx->sigfile, &sig_bytes, -+ &sig_size); -+ if (err) -+ { -+ grub_error (err, N_("Failed to read signed pcr policy file %s"), -+ ctx->sigfile); -+ goto exit1; -+ } -+ -+ err = grub_tpm2_protector_unmarshal_sigfile (sig_bytes, -+ sig_size, -+ &signature); -+ if (err) -+ { -+ grub_error (err, N_("Failed to unmarshal signed PCR policy, ensure the signed " -+ "PCR policy file is in TPM wire format")); -+ goto exit1; -+ } -+ -+ /* Retrieve Sealed Key */ -+ err = grub_tpm2_protector_read_file (ctx->keyfile, &sealed_key_bytes, -+ &sealed_key_size); -+ if (err) -+ { -+ grub_error (err, N_("Failed to read key file %s"), ctx->keyfile); -+ goto exit1; -+ } -+ -+ err = grub_tpm2_protector_unmarshal_keyfile (sealed_key_bytes, -+ sealed_key_size, -+ &sealed_key); -+ if (err) -+ { -+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in " -+ "TPM wire format")); -+ goto exit1; -+ } -+ -+ /* Reproduce the policy signed by the public key */ -+ err = grub_tpm2_protector_authpol_digest (ctx, &pcr_policy); -+ if (err) -+ { -+ grub_error (err, N_("Failed to get the policy digest")); -+ goto exit1; -+ } -+ -+ /* Load the public key */ -+ rc = TPM2_LoadExternal (NULL, NULL, &pub_key, TPM_RH_OWNER, -+ &pubkey_handle, &pubname, NULL); -+ if (rc) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to load public key (TPM2_LoadExternal failed " -+ "with TSS/TPM error %u)"), rc); -+ goto exit1; -+ } -+ -+ /* Calculate the digest of the polcy for VerifySignature */ -+ rc = TPM2_Hash (NULL, (TPM2B_MAX_BUFFER *)&pcr_policy, TPM_ALG_SHA256, -+ TPM_RH_NULL, &pcr_policy_hash, NULL, NULL); -+ if (rc) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to create PCR policy hash (TPM2_Hash failed " -+ "with TSS/TPM error %u)"), rc); -+ goto exit2; -+ } -+ -+ /* Verify the signature against the public key and the reproduced policy digest */ -+ rc = TPM2_VerifySignature (pubkey_handle, NULL, &pcr_policy_hash, &signature, -+ &verification_ticket, NULL); -+ if (rc) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to verify signature (TPM2_VerifySignature " -+ "failed with TSS/TPM error %u)"), rc); -+ goto exit2; -+ } -+ -+ /* Get the handle of the primary storage key */ -+ err = grub_tpm2_protector_srk_get (ctx, &primary_handle); -+ if (err) -+ { -+ grub_error (err, N_("Failed to create primary")); -+ goto exit2; -+ } -+ -+ /* Load Sealed Key */ -+ /* Use the password session with an empty password */ -+ grub_memset (&authCmd, 0, sizeof (authCmd)); -+ authCmd.sessionHandle = TPM_RS_PW; -+ /* Load the sealed object into TPM */ -+ rc = TPM2_Load (primary_handle, &authCmd, &sealed_key.private, &sealed_key.public, -+ &sealed_key_handle, NULL, NULL); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to load sealed key (TPM2_Load failed with " -+ "TSS/TPM error %u)"), rc); -+ goto exit3; -+ } -+ -+ /* Start a policy session to authorize the signed policy */ -+ symmetric.algorithm = TPM_ALG_AES; -+ symmetric.keyBits.aes = 128; -+ symmetric.mode.aes = TPM_ALG_CFB; -+ nonceCaller.size = TPM_SHA256_DIGEST_SIZE; -+ -+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonceCaller, NULL, -+ TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, -+ &session, NULL, NULL); -+ if (rc) -+ { -+ grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession " -+ "failed with TSS/TPM error %u)"), rc); -+ goto exit4; -+ } -+ -+ /* Send the PolicyPCR command to generate the policy digest based on the */ -+ /* current PCR values */ -+ rc = TPM2_PolicyPCR (session, NULL, NULL, &ctx->pcr_list, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed " -+ "with TSS/TPM error: 0x%u).\n"), rc); -+ goto exit5; -+ } -+ -+ /* Authorize the signed policy with the public key and the verification ticket */ -+ rc = TPM2_PolicyAuthorize (session, NULL, &pcr_policy, NULL, &pubname, -+ &verification_ticket, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to authorize PCR policy (TPM2_PolicyAuthorize " -+ "failed with TSS/TPM error: 0x%u).\n"), rc); -+ goto exit5; -+ } -+ -+ /* Unseal the key with the policy session that authorizes the signed policy */ -+ grub_memset (&authCmd, 0, sizeof (authCmd)); -+ authCmd.sessionHandle = session; -+ rc = TPM2_Unseal (sealed_key_handle, &authCmd, &data, NULL); -+ if (rc != TPM_RC_SUCCESS) -+ { -+ err = GRUB_ERR_BAD_DEVICE; -+ grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed" -+ "with TSS/TPM error: 0x%u).\n"), rc); -+ grub_millisleep(500); -+ goto exit5; -+ } -+ -+ /* Epilogue */ -+ key_out = grub_malloc (data.size); -+ if (!key_out) -+ { -+ err = GRUB_ERR_OUT_OF_MEMORY; -+ grub_error (err, N_("No memory left to allocate unlock key buffer")); -+ goto exit4; -+ } -+ -+ grub_printf("TPM2: unsealed %u bytes of key material\n", data.size); -+ -+ if (ctx->efivar) -+ { -+ rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar); -+ if (rc) -+ goto exit4; -+ } -+ -+ grub_memcpy (key_out, data.buffer, data.size); -+ -+ *key = key_out; -+ *key_size = data.size; -+ -+ err = GRUB_ERR_NONE; -+ -+exit5: -+ TPM2_FlushContext (session); -+ -+exit4: -+ TPM2_FlushContext (sealed_key_handle); -+ -+exit3: -+ TPM2_FlushContext (primary_handle); -+ -+exit2: -+ TPM2_FlushContext (pubkey_handle); -+ -+exit1: -+ grub_free (sealed_key_bytes); -+ grub_free (pub_key_bytes); -+ grub_free (sig_bytes); -+ -+ return err; -+} -+ - static grub_err_t - grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx, - grub_uint8_t **key, grub_size_t *key_size) -@@ -496,6 +1008,8 @@ grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx, - return grub_tpm2_protector_srk_recover (ctx, key, key_size); - case GRUB_TPM2_PROTECTOR_MODE_NV: - return grub_tpm2_protector_nv_recover (ctx, key, key_size); -+ case GRUB_TPM2_PROTECTOR_MODE_AUTHPOL: -+ return grub_tpm2_protector_authpol_recover (ctx, key, key_size); - default: - return GRUB_ERR_BAD_ARGUMENT; - } -@@ -543,7 +1057,10 @@ initialize_pcr_list (struct grub_tpm2_protector_context *ctx) - static grub_err_t - grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) - { -- if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET && ctx->keyfile && -+ ctx->pkfile && ctx->sigfile) -+ ctx->mode = GRUB_TPM2_PROTECTOR_MODE_AUTHPOL; -+ else if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET) - ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK; - - /* Checks for SRK mode */ -@@ -556,6 +1073,14 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("In SRK mode, an NV Index cannot be specified")); - -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->pkfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In SRK mode, an a public key cannot be specified")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->sigfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In SRK mode, an a signed pcr policy cannot be specified")); -+ - /* Checks for NV mode */ - if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && !ctx->nv) - return grub_error (GRUB_ERR_BAD_ARGUMENT, -@@ -575,6 +1100,34 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) - N_("In NV Index mode, an asymmetric key type cannot be " - "specified")); - -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->pkfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, an a public key cannot be specified")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->sigfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In NV Index mode, an a signed pcr policy cannot be specified")); -+ -+ /* Checks for Authorized Policy mode */ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->keyfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In Authorized Policy mode, a key file must be specified: " -+ "--keyfile or -k")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->pkfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In Authorized Policy mode, a public key file must be specified: " -+ "--pkfile or -P")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && !ctx->sigfile) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In Authorized Policy mode, a signed pcr file must be specified: " -+ "--sigfile or -S")); -+ -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL && ctx->nv) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ N_("In Authorized Policy mode, an NV Index cannot be specified")); -+ - /* Defaults assignment */ - if (!ctx->bank) - ctx->bank = TPM_ALG_SHA256; -@@ -585,7 +1138,8 @@ grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx) - ctx->pcr_count = 1; - } - -- if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK) -+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK || -+ ctx->mode == GRUB_TPM2_PROTECTOR_MODE_AUTHPOL) - { - if (!ctx->srk) - ctx->srk = TPM2_SRK_HANDLE; -@@ -619,6 +1173,18 @@ grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) - return grub_tpm2_protector_parse_string (value, keyfile, "keyfile"); - } - -+static grub_err_t -+grub_tpm2_protector_parse_pkfile (const char *value, const char **pkfile) -+{ -+ return grub_tpm2_protector_parse_string (value, pkfile, "pkfile"); -+} -+ -+static grub_err_t -+grub_tpm2_protector_parse_sigfile (const char *value, const char **sigfile) -+{ -+ return grub_tpm2_protector_parse_string (value, sigfile, "sigfile"); -+} -+ - static grub_err_t - grub_tpm2_protector_parse_efivar (const char *value, const char **efivar) - { -@@ -633,6 +1199,8 @@ grub_tpm2_protector_parse_mode (const char *value, - *mode = GRUB_TPM2_PROTECTOR_MODE_SRK; - else if (grub_strcmp (value, "nv") == 0) - *mode = GRUB_TPM2_PROTECTOR_MODE_NV; -+ else if (grub_strcmp (value, "authpol") == 0) -+ *mode = GRUB_TPM2_PROTECTOR_MODE_AUTHPOL; - else - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("Value '%s' is not a valid TPM2 key protector mode"), -@@ -722,6 +1290,22 @@ grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc, - return err; - } - -+ if (state[8].set) /* pkfile */ -+ { -+ err = grub_tpm2_protector_parse_pkfile (state[8].arg, -+ &grub_tpm2_protector_ctx.pkfile); -+ if (err) -+ return err; -+ } -+ -+ if (state[9].set) /* sigfile */ -+ { -+ err = grub_tpm2_protector_parse_sigfile (state[9].arg, -+ &grub_tpm2_protector_ctx.sigfile); -+ if (err) -+ return err; -+ } -+ - err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); - - /* This command only initializes the protector, so nothing else to do. */ -@@ -739,6 +1323,8 @@ grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ - N_("tpm2_key_protector_clear accepts no arguments")); - - grub_free ((void *) grub_tpm2_protector_ctx.keyfile); -+ grub_free ((void *) grub_tpm2_protector_ctx.pkfile); -+ grub_free ((void *) grub_tpm2_protector_ctx.sigfile); - grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); - - return GRUB_ERR_NONE; -@@ -761,7 +1347,9 @@ GRUB_MOD_INIT (tpm2) - "[-k sealed_key_file_path] " - "[-s srk_handle] " - "[-a asymmetric_key_type] " -- "[-n nv_index]"), -+ "[-n nv_index] " -+ "[-P public_key_file_path] " -+ "[-S signature_file_path]"), - N_("Initialize the TPM2 key protector."), - grub_tpm2_protector_init_cmd_options); - grub_tpm2_protector_clear_cmd = -@@ -775,6 +1363,8 @@ GRUB_MOD_INIT (tpm2) - GRUB_MOD_FINI (tpm2) - { - grub_free ((void *) grub_tpm2_protector_ctx.keyfile); -+ grub_free ((void *) grub_tpm2_protector_ctx.pkfile); -+ grub_free ((void *) grub_tpm2_protector_ctx.sigfile); - grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx)); - - grub_key_protector_unregister (&grub_tpm2_key_protector); --- -2.35.3 - diff --git a/fix-tpm2-build.patch b/fix-tpm2-build.patch deleted file mode 100644 index 2a4fc24..0000000 --- a/fix-tpm2-build.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- - grub-core/Makefile.core.def | 1 + - grub-core/tpm2/module.c | 2 +- - util/grub-protect.c | 2 +- - 3 files changed, 3 insertions(+), 2 deletions(-) - ---- a/grub-core/Makefile.core.def -+++ b/grub-core/Makefile.core.def -@@ -2569,6 +2569,7 @@ - common = tpm2/mu.c; - common = tpm2/tpm2.c; - efi = tpm2/tcg2.c; -+ enable = efi; - }; - - module = { ---- a/util/grub-protect.c -+++ b/util/grub-protect.c -@@ -542,7 +542,7 @@ - if (pcr_values.digests[i].size != pcr_digest_len) - { - fprintf (stderr, -- _("Bad PCR value size: expected %lu bytes but got %u bytes.\n"), -+ _("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but got %u bytes.\n"), - pcr_digest_len, pcr_values.digests[i].size); - goto exit2; - } ---- a/grub-core/tpm2/module.c -+++ b/grub-core/tpm2/module.c -@@ -195,7 +195,7 @@ - if (sealed_key_size > buf.cap) - { - grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer " -- "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap); -+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", sealed_key_size, buf.cap); - return GRUB_ERR_BAD_ARGUMENT; - } - diff --git a/grub-read-pcr.patch b/grub-read-pcr.patch index c4d0fa3..68732d4 100644 --- a/grub-read-pcr.patch +++ b/grub-read-pcr.patch @@ -42,7 +42,7 @@ Index: grub-2.06/grub-core/commands/efi/tpm.c + pcr = &o->pcrSelections[o->count++]; + pcr->hash = algo; + pcr->sizeOfSelect = 3; -+ pcr->pcrSelect[TPM2_PCR_TO_SELECT(pcrIndex)] |= TPM2_PCR_TO_BIT(pcrIndex); ++ TPMS_PCR_SELECTION_SelectPCR (pcr, pcrIndex); +} + +struct grub_tpm_hash_info { diff --git a/grub-unseal-debug.patch b/grub-unseal-debug.patch deleted file mode 100644 index 2d9225b..0000000 --- a/grub-unseal-debug.patch +++ /dev/null @@ -1,41 +0,0 @@ -Index: grub-2.06/grub-core/tpm2/module.c -=================================================================== ---- grub-2.06.orig/grub-core/tpm2/module.c -+++ grub-2.06/grub-core/tpm2/module.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -449,6 +450,7 @@ grub_tpm2_protector_srk_recover (const s - { - grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed " - "with TSS/TPM error %u)"), rc); -+ grub_millisleep(500); - goto exit4; - } - -@@ -461,6 +463,8 @@ grub_tpm2_protector_srk_recover (const s - goto exit4; - } - -+ grub_printf("TPM2: unsealed %u bytes of key material\n", data.size); -+ - if (ctx->efivar) - { - rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar); -Index: grub-2.06/grub-core/loader/linux.c -=================================================================== ---- grub-2.06.orig/grub-core/loader/linux.c -+++ grub-2.06/grub-core/loader/linux.c -@@ -171,6 +171,7 @@ grub_initrd_component (const char *buf, - struct grub_linux_initrd_component *comp = initrd_ctx->components + initrd_ctx->nfiles; - grub_size_t dir_size, name_len; - -+ grub_printf("Creating initrd component \"%s\" with %u bytes\n", newc_name, bufsz); - while (*newc_name == '/') - newc_name++; - diff --git a/grub2.changes b/grub2.changes index 59db128..234b0c1 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,46 @@ +------------------------------------------------------------------- +Fri Apr 21 07:53:30 UTC 2023 - Gary Ching-Pang Lin + +- Update TPM 2.0 key unsealing patches + * Add the new upstreaming patches + 0001-protectors-Add-key-protectors-framework.patch + 0002-tpm2-Add-TPM-Software-Stack-TSS.patch + 0003-protectors-Add-TPM2-Key-Protector.patch + 0004-cryptodisk-Support-key-protectors.patch + 0005-util-grub-protect-Add-new-tool.patch + * Add the authorized policy patches based on the upstreaming + patches + 0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch + 0002-tpm2-Add-more-marshal-unmarshal-functions.patch + 0003-tpm2-Implement-more-TPM2-commands.patch + 0004-tpm2-Support-authorized-policy.patch + * Drop the old patches + 0010-protectors-Add-key-protectors-framework.patch + 0011-tpm2-Add-TPM-Software-Stack-TSS.patch + 0012-protectors-Add-TPM2-Key-Protector.patch + 0013-cryptodisk-Support-key-protectors.patch + 0014-util-grub-protect-Add-new-tool.patch + fix-tpm2-build.patch + tpm-protector-dont-measure-sealed-key.patch + tpm-protector-export-secret-key.patch + grub-unseal-debug.patch + 0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch + 0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch + 0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch + 0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch + 0005-tpm2-add-more-marshal-unmarshal-functions.patch + 0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch + 0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch + 0008-tpm2-allow-some-command-parameters-to-be-NULL.patch + 0009-tpm2-remove-the-unnecessary-variables.patch + 0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch + 0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch + 0012-tpm2-initialize-the-PCR-selection-list-early.patch + 0013-tpm2-support-unsealing-key-with-authorized-policy.patch + * Refresh grub-read-pcr.patch + * Introduce a new build requirement: libtasn1-devel +- Only package grub2-protect for the architectures with EFI support + ------------------------------------------------------------------- Fri Apr 21 04:53:54 UTC 2023 - Michael Chang diff --git a/grub2.spec b/grub2.spec index 20ddd0b..0ed977c 100644 --- a/grub2.spec +++ b/grub2.spec @@ -48,6 +48,7 @@ BuildRequires: dejavu-fonts BuildRequires: gnu-unifont %endif BuildRequires: help2man +BuildRequires: libtasn1-devel BuildRequires: xz %if 0%{?suse_version} >= 1210 BuildRequires: makeinfo @@ -413,13 +414,15 @@ Patch890: 0006-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch Patch891: 0007-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch Patch892: 0008-cryptodisk-Move-global-variables-into-grub_cryptomou.patch Patch893: 0009-cryptodisk-Improve-handling-of-partition-name-in-cry.patch -Patch894: 0010-protectors-Add-key-protectors-framework.patch -Patch895: 0011-tpm2-Add-TPM-Software-Stack-TSS.patch -Patch896: 0012-protectors-Add-TPM2-Key-Protector.patch -Patch897: 0013-cryptodisk-Support-key-protectors.patch -Patch898: 0014-util-grub-protect-Add-new-tool.patch -Patch899: fix-tpm2-build.patch -Patch900: 0001-crytodisk-fix-cryptodisk-module-looking-up.patch + +# TPM 2.0 protector +Patch894: 0001-protectors-Add-key-protectors-framework.patch +Patch895: 0002-tpm2-Add-TPM-Software-Stack-TSS.patch +Patch896: 0003-protectors-Add-TPM2-Key-Protector.patch +Patch897: 0004-cryptodisk-Support-key-protectors.patch +Patch898: 0005-util-grub-protect-Add-new-tool.patch +Patch899: 0001-crytodisk-fix-cryptodisk-module-looking-up.patch + # fde Patch901: 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch Patch902: 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch @@ -434,10 +437,8 @@ Patch910: 0010-templates-import-etc-crypttab-to-grub.cfg.patch Patch911: grub-read-pcr.patch Patch912: efi-set-variable-with-attrs.patch Patch913: tpm-record-pcrs.patch -Patch914: tpm-protector-dont-measure-sealed-key.patch -Patch915: tpm-protector-export-secret-key.patch + Patch916: grub-install-record-pcrs.patch -Patch917: grub-unseal-debug.patch # efi mm Patch919: 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch Patch920: 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch @@ -480,19 +481,13 @@ Patch953: grub2-increase-crypttab-path-buffer.patch Patch954: 0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch Patch955: 0001-grub-core-modify-sector-by-sysfs-as-disk-sector.patch Patch956: 0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch -Patch957: 0001-tpm2-adjust-the-input-parameters-of-TPM2_EvictContro.patch -Patch958: 0002-tpm2-declare-the-input-arguments-of-TPM2-functions-a.patch -Patch959: 0003-tpm2-resend-the-command-on-TPM_RC_RETRY.patch -Patch960: 0004-tpm2-add-new-TPM2-types-structures-and-command-const.patch -Patch961: 0005-tpm2-add-more-marshal-unmarshal-functions.patch -Patch962: 0006-tpm2-check-the-command-parameters-of-TPM2-commands.patch -Patch963: 0007-tpm2-pack-the-missing-authorization-command-for-TPM2.patch -Patch964: 0008-tpm2-allow-some-command-parameters-to-be-NULL.patch -Patch965: 0009-tpm2-remove-the-unnecessary-variables.patch -Patch966: 0010-tpm2-add-TPM2-commands-to-support-authorized-policy.patch -Patch967: 0011-tpm2-make-the-file-reading-unmarshal-functions-gener.patch -Patch968: 0012-tpm2-initialize-the-PCR-selection-list-early.patch -Patch969: 0013-tpm2-support-unsealing-key-with-authorized-policy.patch + +# Support TPM 2.0 Authorized Policy +Patch957: 0001-tpm2-Add-TPM2-types-structures-and-command-constants.patch +Patch958: 0002-tpm2-Add-more-marshal-unmarshal-functions.patch +Patch959: 0003-tpm2-Implement-more-TPM2-commands.patch +Patch960: 0004-tpm2-Support-authorized-policy.patch + # Set efi variables LoaderDevicePartUUID & LoaderInfo (needed for UKI) Patch970: grub2-add-module-for-boot-loader-interface.patch # Fix out of memory error on lpar installation from virtual cdrom (bsc#1208024) @@ -1415,7 +1410,9 @@ fi %{_bindir}/%{name}-render-label %{_bindir}/%{name}-script-check %{_bindir}/%{name}-syslinux2cfg +%ifarch %{efi} %{_bindir}/%{name}-protect +%endif %if 0%{?has_systemd:1} %{_unitdir}/grub2-once.service %endif diff --git a/tpm-protector-dont-measure-sealed-key.patch b/tpm-protector-dont-measure-sealed-key.patch deleted file mode 100644 index 8357e74..0000000 --- a/tpm-protector-dont-measure-sealed-key.patch +++ /dev/null @@ -1,15 +0,0 @@ -Index: grub-2.06/grub-core/tpm2/module.c -=================================================================== ---- grub-2.06.orig/grub-core/tpm2/module.c -+++ grub-2.06/grub-core/tpm2/module.c -@@ -139,7 +139,9 @@ grub_tpm2_protector_srk_read_keyfile (co - void *sealed_key_buffer; - grub_off_t sealed_key_read; - -- sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE); -+ /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9 -+ * otherwise we'll never be able to predict the value of PCR9 at unseal time */ -+ sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); - if (!sealed_key_file) - { - grub_dprintf ("tpm2", "Could not open sealed key file.\n"); diff --git a/tpm-protector-export-secret-key.patch b/tpm-protector-export-secret-key.patch deleted file mode 100644 index 70eb493..0000000 --- a/tpm-protector-export-secret-key.patch +++ /dev/null @@ -1,138 +0,0 @@ -Index: grub-2.06/grub-core/tpm2/module.c -=================================================================== ---- grub-2.06.orig/grub-core/tpm2/module.c -+++ grub-2.06/grub-core/tpm2/module.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - GRUB_MOD_LICENSE ("GPLv3+"); - -@@ -46,6 +47,7 @@ struct grub_tpm2_protector_context - const char *keyfile; - TPM_HANDLE srk; - TPM_HANDLE nv; -+ const char *efivar; - }; - - static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] = -@@ -122,6 +124,16 @@ static const struct grub_arg_option grub - N_("Required in NV Index mode, the NV handle to read which must " - "readily exist on the TPM and which contains the key."), - }, -+ /* When publishing the unsealed key to a UEFI variable */ -+ { -+ .longarg = "efivar", -+ .shortarg = 'E', -+ .flags = 0, -+ .arg = NULL, -+ .type = ARG_TYPE_STRING, -+ .doc = -+ N_("Publish the unsealed key to the indicated UEFI variable."), -+ }, - /* End of list */ - {0, 0, 0, 0, 0, 0} - }; -@@ -302,6 +314,34 @@ grub_tpm2_protector_srk_get (const struc - } - - static grub_err_t -+grub_tpm2_protector_publish_key (grub_uint8_t *key, grub_size_t key_size, -+ const char *var_name) -+{ -+ grub_efi_guid_t vendor_guid = { 0x58aca851, 0x8af7, 0x4738, { 0xa5, 0x42, 0x26, 0x6e, 0x21, 0xf5, 0xca, 0xd9 }}; -+ grub_uint8_t *tmp_key; -+ grub_err_t err; -+ -+ /* It appears that EFI's set_var function overwrites the key. */ -+ tmp_key = grub_malloc (key_size); -+ if (!tmp_key) -+ { -+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("No memory left to allocate temporary key buffer")); -+ return GRUB_ERR_OUT_OF_MEMORY; -+ } -+ -+ grub_memcpy(tmp_key, key, key_size); -+ -+ err = grub_efi_set_variable_with_attributes(var_name, &vendor_guid, -+ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS, -+ tmp_key, key_size); -+ if (err) -+ grub_error (err, N_("Failed to export LUKS key as EFI variable %s"), var_name); -+ -+ grub_free (tmp_key); -+ return err; -+} -+ -+static grub_err_t - grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx, - grub_uint8_t **key, grub_size_t *key_size) - { -@@ -421,6 +461,13 @@ grub_tpm2_protector_srk_recover (const s - goto exit4; - } - -+ if (ctx->efivar) -+ { -+ rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar); -+ if (rc) -+ goto exit4; -+ } -+ - grub_memcpy (key_out, data.buffer, data.size); - - *key = key_out; -@@ -549,20 +596,32 @@ grub_tpm2_protector_check_args (struct g - } - - static grub_err_t --grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) -+grub_tpm2_protector_parse_string (const char *value, const char **var, const char *arg_name) - { - if (grub_strlen (value) == 0) - return GRUB_ERR_BAD_ARGUMENT; - -- *keyfile = grub_strdup (value); -- if (!*keyfile) -+ *var = grub_strdup (value); -+ if (!*var) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, -- N_("No memory to duplicate keyfile path")); -+ N_("No memory to duplicate %s argument"), arg_name); - - return GRUB_ERR_NONE; - } - - static grub_err_t -+grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile) -+{ -+ return grub_tpm2_protector_parse_string (value, keyfile, "keyfile"); -+} -+ -+static grub_err_t -+grub_tpm2_protector_parse_efivar (const char *value, const char **efivar) -+{ -+ return grub_tpm2_protector_parse_string (value, efivar, "efivar"); -+} -+ -+static grub_err_t - grub_tpm2_protector_parse_mode (const char *value, - grub_tpm2_protector_mode_t *mode) - { -@@ -650,6 +709,14 @@ grub_tpm2_protector_init_cmd_handler (gr - if (err) - return err; - } -+ -+ if (state[7].set) /* efivar */ -+ { -+ err = grub_tpm2_protector_parse_efivar (state[7].arg, -+ &grub_tpm2_protector_ctx.efivar); -+ if (err) -+ return err; -+ } - - err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx); -