3838#define KM_HASH_USAGE_SDEV (1 << 3)
3939#define KM_HASH_USAGE_PFR_CPLD (1 << 4)
4040
41+ /*
42+ * SRTM version is an upper-case hex dump of ACM's "Date" (offset 20) and "TXT SVN" (offset 28)
43+ * fields as a NUL-terminated UTF16 string.
44+ */
45+ #define SCRTM_VERSION_LENGTH 13
46+
4147/*
4248 * Definitions of the structures come from Intel document #575623 CBnT BWG v1.2.5 ("Intel
4349 * Converged Boot Guard and Intel Trusted Execution Technology (Intel TXT) BIOS Specification").
@@ -179,7 +185,8 @@ static const void *find_in_fit(uint8_t type, size_t *size)
179185 return addr ;
180186}
181187
182- static enum cb_err get_ibbs_flags (bool * auth_measure , uint64_t * biosacm_sts_mask )
188+ static enum cb_err get_flags (bool * conventional_measurements , bool * auth_measure ,
189+ uint64_t * biosacm_sts_mask )
183190{
184191 size_t bpm_len ;
185192 const struct bpm_header * bpm = find_in_fit (FIT_ENTRY_TYPE_BPM , & bpm_len );
@@ -188,6 +195,11 @@ static enum cb_err get_ibbs_flags(bool *auth_measure, uint64_t *biosacm_sts_mask
188195 return CB_ERR ;
189196 }
190197
198+ /* Meteor Lake seems to be the first generation with new (more TCG-like) style of
199+ measurements. */
200+ * conventional_measurements = !CONFIG (SOC_INTEL_METEORLAKE )
201+ && !CONFIG (SOC_INTEL_PANTHERLAKE_BASE );
202+
191203 const struct bpm_ibbs * ibbs = (const void * )bpm -> se_element ;
192204 * auth_measure = (ibbs -> flags & BPM_IBBS_FLAG_AUTH_MEASURE ) != 0 ;
193205 * biosacm_sts_mask =
@@ -613,6 +625,13 @@ static enum cb_err cap_pcrs(union cbnt_biosacm_policy biosacm_sts)
613625 return CB_SUCCESS ;
614626}
615627
628+ static char hex_digit (int nibble )
629+ {
630+ if (nibble < 10 )
631+ return '0' + nibble ;
632+ return 'A' + nibble - 10 ;
633+ }
634+
616635void intel_cbnt_inject_ibg_measurements (void )
617636{
618637 const union cbnt_biosacm_policy biosacm_sts = {
@@ -639,25 +658,11 @@ void intel_cbnt_inject_ibg_measurements(void)
639658 return ;
640659 }
641660
642- /*
643- * Making and hashing PCR-0 data.
644- *
645- * Pseudo-code of the data to be measured into PCR-0 for TigerLake and newer (older
646- * hardware isn't supported yet):
647- *
648- * struct {
649- * uint64_t ACM_POLICY_STATUS;
650- * uint16_t ACM.Header.SVN;
651- * uint8_t ACM.Signature[ACM signature size];
652- * uint8_t KM.Signature[KM signature size];
653- * uint8_t BPM.Signature[BPM signature size];
654- * uint8_t IBB.Digest[IBB digest size];
655- * } PCR0_DATA;
656- */
657-
661+ bool conventional_measurements ;
658662 bool auth_measure ;
659663 uint64_t biosacm_sts_mask ;
660- if (get_ibbs_flags (& auth_measure , & biosacm_sts_mask ) != CB_SUCCESS ) {
664+ if (get_flags (& conventional_measurements , & auth_measure , & biosacm_sts_mask ) !=
665+ CB_SUCCESS ) {
661666 printk (BIOS_ERR , "CBnT: failed to obtain IBBS flags from BPM\n" );
662667 return ;
663668 }
@@ -671,52 +676,151 @@ void intel_cbnt_inject_ibg_measurements(void)
671676 struct obuf data_ob ;
672677 obuf_init (& data_ob , data , sizeof (data ));
673678
674- /* ACM_POLICY_STATUS (won't run out of space on this one) */
675- (void )obuf_write_le64 (& data_ob , biosacm_sts .raw & biosacm_sts_mask );
679+ if (conventional_measurements ) {
680+ /*
681+ * Making and hashing PCR-0 data.
682+ *
683+ * Pseudo-code of the data to be measured into PCR-0 for TigerLake and newer
684+ * (older hardware isn't supported yet):
685+ *
686+ * struct {
687+ * uint64_t ACM_POLICY_STATUS;
688+ * uint16_t ACM.Header.SVN;
689+ * uint8_t ACM.Signature[ACM signature size];
690+ * uint8_t KM.Signature[KM signature size];
691+ * uint8_t BPM.Signature[BPM signature size];
692+ * uint8_t IBB.Digest[IBB digest size];
693+ * } PCR0_DATA;
694+ */
695+
696+ /* ACM_POLICY_STATUS (won't run out of space on this one) */
697+ (void )obuf_write_le64 (& data_ob , biosacm_sts .raw & biosacm_sts_mask );
698+
699+ if (fill_pcr0_acm_fields (& data_ob ) != CB_SUCCESS ) {
700+ printk (BIOS_ERR ,
701+ "CBnT: failed to fill ACM fields of PCR-0 measurement data\n" );
702+ return ;
703+ }
676704
677- if (fill_pcr0_acm_fields (& data_ob ) != CB_SUCCESS ) {
678- printk (BIOS_ERR , "CBnT: failed to fill ACM fields of PCR-0 measurement data\n" );
679- return ;
680- }
705+ if (copy_km_signature (& data_ob ) != CB_SUCCESS ) {
706+ printk (BIOS_ERR ,
707+ "CBnT: failed to copy KM signature for PCR-0 measurement\n" );
708+ return ;
709+ }
681710
682- if (copy_km_signature (& data_ob ) != CB_SUCCESS ) {
683- printk (BIOS_ERR , "CBnT: failed to copy KM signature for PCR-0 measurement\n" );
684- return ;
685- }
711+ if (copy_bpm_signature (& data_ob ) != CB_SUCCESS ) {
712+ printk (BIOS_ERR ,
713+ "CBnT: failed to copy BPM signature for PCR-0 measurement\n" );
714+ return ;
715+ }
686716
687- if (copy_bpm_signature (& data_ob ) != CB_SUCCESS ) {
688- printk (BIOS_ERR , "CBnT: failed to copy BPM signature for PCR-0 measurement\n" );
689- return ;
690- }
717+ struct vb2_hash hash ;
718+ if (vb2_hash_calculate (vboot_hwcrypto_allowed (), data ,
719+ obuf_nr_written (& data_ob ), tpm_log_alg (), & hash )) {
720+ printk (BIOS_ERR , "CBnT: failed to hash PCR-0 measurement data\n" );
721+ return ;
722+ }
691723
692- struct vb2_hash hash ;
693- if (vb2_hash_calculate (vboot_hwcrypto_allowed (), data , obuf_nr_written (& data_ob ),
694- tpm_log_alg (), & hash )) {
695- printk (BIOS_ERR , "CBnT: failed to hash PCR-0 measurement data\n" );
696- return ;
697- }
724+ /* Per BWG this should be logged with EV_S_CRTM_CONTENTS type. */
725+ tpm_log_add_table_entry (CBNT_EVENT_LOG_MESSAGE , 0 , hash .algo , hash .raw ,
726+ vb2_digest_size (hash .algo ));
698727
699- /* Per BWG this should be logged with EV_S_CRTM_CONTENTS type. */
700- tpm_log_add_table_entry (CBNT_EVENT_LOG_MESSAGE , 0 , hash .algo , hash .raw ,
701- vb2_digest_size (hash .algo ));
728+ /* Optionally making and hashing PCR-7 data (not supported since MTL). */
729+ if (auth_measure ) {
730+ /* Reuse the first 2 fields of PCR-0 data which are identical in both
731+ cases. */
732+ obuf_init (& data_ob , data , sizeof (data ));
733+ (void )obuf_oob_fill (& data_ob , sizeof (uint64_t ) + sizeof (uint16_t ));
734+
735+ if (!make_pcr7_hash (& data_ob , & hash )) {
736+ printk (BIOS_ERR ,
737+ "CBnT: failed to build and hash PCR-7 measurement data\n" );
738+ return ;
739+ }
740+
741+ /* Per BWG this should be logged with EV_EFI_VARIABLE_DRIVER_CONFIG type
742+ and event name should be a Unicode string. */
743+ tpm_log_add_table_entry (CBNT_EVENT_LOG_MESSAGE , 7 , hash .algo , hash .raw ,
744+ vb2_digest_size (hash .algo ));
745+ printk (BIOS_INFO , "CBnT: reconstructed PCR-7 measurement\n" );
746+ }
702747
703- /* Making and hashing PCR-7 data. */
704- if (auth_measure ) {
705- /* Reuse the first 2 fields of PCR-0 data which are identical in both cases. */
748+ } else {
749+ size_t acm_len ;
750+ const struct acm_header_v3 * acm = find_in_fit (FIT_ENTRY_TYPE_SACM , & acm_len );
751+ if (acm == NULL ) {
752+ printk (BIOS_ERR , "CBnT: failed to find SACM\n" );
753+ return ;
754+ }
755+
756+ uint8_t crtm_version [6 ];
757+ memcpy (& crtm_version [0 ], & acm -> date , 4 );
758+ memcpy (& crtm_version [4 ], & acm -> txt_svn , 2 );
759+
760+ char crtm_version_str [SCRTM_VERSION_LENGTH ] = {0 };
761+ uint16_t crtm_version_utf16 [SCRTM_VERSION_LENGTH ] = {0 };
762+ for (int i = 0 ; i < sizeof (crtm_version ); ++ i ) {
763+ crtm_version_str [i * 2 + 0 ] = hex_digit (crtm_version [i ] >> 4 );
764+ crtm_version_str [i * 2 + 1 ] = hex_digit (crtm_version [i ] & 0xf );
765+
766+ crtm_version_utf16 [i * 2 + 0 ] = crtm_version_str [i * 2 + 0 ];
767+ crtm_version_utf16 [i * 2 + 1 ] = crtm_version_str [i * 2 + 1 ];
768+ }
769+
770+ struct vb2_hash hash ;
771+ if (vb2_hash_calculate (vboot_hwcrypto_allowed (), crtm_version_utf16 ,
772+ sizeof (crtm_version_utf16 ), tpm_log_alg (), & hash )) {
773+ printk (BIOS_ERR , "CBnT: failed to hash CRTM version\n" );
774+ return ;
775+ }
776+ /* Per BWG this should be logged with EV_S_CRTM_VERSION type. */
777+ tpm_log_add_table_entry (crtm_version_str , 0 , hash .algo , hash .raw ,
778+ vb2_digest_size (hash .algo ));
779+
780+ if (copy_ibb_hash (& data_ob , tpm2_alg_from_vb2_hash (tpm_log_alg ())) !=
781+ CB_SUCCESS ) {
782+ printk (BIOS_ERR , "CBnT: failed to obtain IBB digest\n" );
783+ return ;
784+ }
785+ /* Per BWG this should be logged with EV_POST_CODE type. */
786+ tpm_log_add_table_entry ("Boot Guard Measured IBB" , 0 , tpm_log_alg (), data ,
787+ obuf_nr_written (& data_ob ));
788+
789+ /*
790+ * struct {
791+ * uint64_t ACM_POLICY_STATUS;
792+ * uint8_t KM.Signature[KM signature size];
793+ * uint8_t BPM.Signature[BPM signature size];
794+ * } POLICY_DATA;
795+ */
706796 obuf_init (& data_ob , data , sizeof (data ));
707- (void )obuf_oob_fill (& data_ob , sizeof (uint64_t ) + sizeof (uint16_t ));
708797
709- if (!make_pcr7_hash (& data_ob , & hash )) {
798+ /* ACM_POLICY_STATUS (won't run out of space on this one) */
799+ (void )obuf_write_le64 (& data_ob , biosacm_sts .raw & biosacm_sts_mask );
800+ if (copy_acm_signature (& data_ob ) != CB_SUCCESS ) {
801+ printk (BIOS_ERR , "CBnT: failed to copy ACM signature\n" );
802+ return ;
803+ }
804+ if (copy_km_signature (& data_ob ) != CB_SUCCESS ) {
805+ printk (BIOS_ERR , "CBnT: failed to copy KM signature\n" );
806+ return ;
807+ }
808+ if (copy_bpm_signature (& data_ob ) != CB_SUCCESS ) {
710809 printk (BIOS_ERR ,
711- "CBnT: failed to build and hash PCR-7 measurement data\n" );
810+ "CBnT: failed to copy BPM signature for PCR-0 measurement\n" );
811+ return ;
812+ }
813+ if (vb2_hash_calculate (vboot_hwcrypto_allowed (), data ,
814+ obuf_nr_written (& data_ob ), tpm_log_alg (), & hash )) {
815+ printk (BIOS_ERR , "CBnT: failed to hash POLICY_DATA\n" );
816+ return ;
817+ }
818+ /* Per BWG this should be logged with EV_POST_CODE type. */
819+ if (tpm_extend_pcr (0 , hash .algo , hash .raw , vb2_digest_size (hash .algo ),
820+ "BIOS Measured Boot Guard Policy" ) != TPM_SUCCESS ) {
821+ printk (BIOS_ERR , "CBnT: failed to extend POLICY_DATA\n" );
712822 return ;
713823 }
714-
715- /* Per BWG this should be logged with EV_EFI_VARIABLE_DRIVER_CONFIG type and
716- event name should be a Unicode string. */
717- tpm_log_add_table_entry (CBNT_EVENT_LOG_MESSAGE , 7 , hash .algo , hash .raw ,
718- vb2_digest_size (hash .algo ));
719- printk (BIOS_INFO , "CBnT: reconstructed PCR-7 measurement\n" );
720824 }
721825
722826 /*
0 commit comments