|
9 | 9 | #include <xen/macros.h>
|
10 | 10 | #include <xen/mm.h>
|
11 | 11 | #include <xen/types.h>
|
| 12 | +#include <asm/bootinfo.h> |
12 | 13 | #include <asm/e820.h>
|
13 | 14 | #include <asm/intel_txt.h>
|
14 | 15 | #include <asm/page.h>
|
| 16 | +#include <asm/processor.h> |
15 | 17 | #include <asm/slaunch.h>
|
16 | 18 | #include <asm/tpm.h>
|
17 | 19 |
|
@@ -106,3 +108,209 @@ void __init slaunch_reserve_mem_regions(void)
|
106 | 108 | /* Vendor-specific part. */
|
107 | 109 | txt_reserve_mem_regions();
|
108 | 110 | }
|
| 111 | + |
| 112 | +void slaunch_measure_slrt(void) |
| 113 | +{ |
| 114 | + struct slr_table *slrt = get_slrt(); |
| 115 | + |
| 116 | + if ( slrt->revision == 1 ) |
| 117 | + { |
| 118 | + /* |
| 119 | + * In revision one of the SLRT, only platform-specific info table is |
| 120 | + * measured. |
| 121 | + */ |
| 122 | + struct slr_entry_intel_info tmp; |
| 123 | + struct slr_entry_intel_info *entry; |
| 124 | + |
| 125 | + entry = (struct slr_entry_intel_info *) |
| 126 | + slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); |
| 127 | + if ( entry == NULL ) |
| 128 | + panic("SLRT is missing Intel-specific information!\n"); |
| 129 | + |
| 130 | + tmp = *entry; |
| 131 | + tmp.boot_params_base = 0; |
| 132 | + tmp.txt_heap = 0; |
| 133 | + |
| 134 | + tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, |
| 135 | + sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); |
| 136 | + } |
| 137 | + else |
| 138 | + { |
| 139 | + /* |
| 140 | + * get_slrt() checks that the revision is valid, so we must not get |
| 141 | + * here unless the code is wrong. |
| 142 | + */ |
| 143 | + panic("Unhandled SLRT revision: %d!\n", slrt->revision); |
| 144 | + } |
| 145 | +} |
| 146 | + |
| 147 | +static struct slr_entry_policy *slr_get_policy(struct slr_table *slrt) |
| 148 | +{ |
| 149 | + struct slr_entry_policy *policy; |
| 150 | + |
| 151 | + policy = (struct slr_entry_policy *) |
| 152 | + slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DRTM_POLICY); |
| 153 | + if (policy == NULL) |
| 154 | + panic("SLRT is missing DRTM policy!\n"); |
| 155 | + |
| 156 | + /* XXX: are newer revisions allowed? */ |
| 157 | + if ( policy->revision != SLR_POLICY_REVISION ) |
| 158 | + panic("DRTM policy in SLRT is of unsupported revision: %#04x!\n", |
| 159 | + slrt->revision); |
| 160 | + |
| 161 | + return policy; |
| 162 | +} |
| 163 | + |
| 164 | +static void check_slrt_policy_entry(struct slr_policy_entry *policy_entry, |
| 165 | + int idx, |
| 166 | + struct slr_table *slrt) |
| 167 | +{ |
| 168 | + if ( policy_entry->entity_type != SLR_ET_SLRT ) |
| 169 | + panic("Expected DRTM policy entry #%d to describe SLRT, got %#04x!\n", |
| 170 | + idx, policy_entry->entity_type); |
| 171 | + if ( policy_entry->pcr != DRTM_DATA_PCR ) |
| 172 | + panic("SLRT was measured to PCR-%d instead of PCR-%d!\n", DRTM_DATA_PCR, |
| 173 | + policy_entry->pcr); |
| 174 | + if ( policy_entry->entity != (uint64_t)__pa(slrt) ) |
| 175 | + panic("SLRT address (%#08lx) differs from its DRTM entry (%#08lx)\n", |
| 176 | + __pa(slrt), policy_entry->entity); |
| 177 | +} |
| 178 | + |
| 179 | +/* Returns number of policy entries that were already measured. */ |
| 180 | +static unsigned int check_drtm_policy(struct slr_table *slrt, |
| 181 | + struct slr_entry_policy *policy, |
| 182 | + struct slr_policy_entry *policy_entry, |
| 183 | + const struct boot_info *bi) |
| 184 | +{ |
| 185 | + uint32_t i; |
| 186 | + uint32_t num_mod_entries; |
| 187 | + |
| 188 | + if ( policy->nr_entries < 2 ) |
| 189 | + panic("DRTM policy in SLRT contains less than 2 entries (%d)!\n", |
| 190 | + policy->nr_entries); |
| 191 | + |
| 192 | + /* |
| 193 | + * MBI policy entry must be the first one, so that measuring order matches |
| 194 | + * policy order. |
| 195 | + */ |
| 196 | + if ( policy_entry[0].entity_type != SLR_ET_MULTIBOOT2_INFO ) |
| 197 | + panic("First entry of DRTM policy in SLRT is not MBI: %#04x!\n", |
| 198 | + policy_entry[0].entity_type); |
| 199 | + if ( policy_entry[0].pcr != DRTM_DATA_PCR ) |
| 200 | + panic("MBI was measured to %d instead of %d PCR!\n", DRTM_DATA_PCR, |
| 201 | + policy_entry[0].pcr); |
| 202 | + |
| 203 | + /* SLRT policy entry must be the second one. */ |
| 204 | + check_slrt_policy_entry(&policy_entry[1], 1, slrt); |
| 205 | + |
| 206 | + for ( i = 0; i < bi->nr_modules; i++ ) |
| 207 | + { |
| 208 | + uint16_t j; |
| 209 | + const struct boot_module *mod = &bi->mods[i]; |
| 210 | + |
| 211 | + if (mod->relocated || mod->released) |
| 212 | + { |
| 213 | + panic("Multiboot module \"%s\" (at %d) was consumed before measurement\n", |
| 214 | + (const char *)__va(mod->cmdline_pa), i); |
| 215 | + } |
| 216 | + |
| 217 | + for ( j = 2; j < policy->nr_entries; j++ ) |
| 218 | + { |
| 219 | + if ( policy_entry[j].entity_type != SLR_ET_MULTIBOOT2_MODULE ) |
| 220 | + continue; |
| 221 | + |
| 222 | + if ( policy_entry[j].entity == mod->start && |
| 223 | + policy_entry[j].size == mod->size ) |
| 224 | + break; |
| 225 | + } |
| 226 | + |
| 227 | + if ( j >= policy->nr_entries ) |
| 228 | + { |
| 229 | + panic("Couldn't find Multiboot module \"%s\" (at %d) in DRTM of Secure Launch\n", |
| 230 | + (const char *)__va(mod->cmdline_pa), i); |
| 231 | + } |
| 232 | + } |
| 233 | + |
| 234 | + num_mod_entries = 0; |
| 235 | + for ( i = 0; i < policy->nr_entries; i++ ) |
| 236 | + { |
| 237 | + if ( policy_entry[i].entity_type == SLR_ET_MULTIBOOT2_MODULE ) |
| 238 | + num_mod_entries++; |
| 239 | + } |
| 240 | + |
| 241 | + if ( bi->nr_modules != num_mod_entries ) |
| 242 | + { |
| 243 | + panic("Unexpected number of Multiboot modules: %d instead of %d\n", |
| 244 | + (int)bi->nr_modules, (int)num_mod_entries); |
| 245 | + } |
| 246 | + |
| 247 | + /* |
| 248 | + * MBI was measured in tpm_extend_mbi(). |
| 249 | + * SLRT was measured in tpm_measure_slrt(). |
| 250 | + */ |
| 251 | + return 2; |
| 252 | +} |
| 253 | + |
| 254 | +void slaunch_process_drtm_policy(const struct boot_info *bi) |
| 255 | +{ |
| 256 | + struct slr_table *slrt; |
| 257 | + struct slr_entry_policy *policy; |
| 258 | + struct slr_policy_entry *policy_entry; |
| 259 | + uint16_t i; |
| 260 | + unsigned int measured; |
| 261 | + |
| 262 | + slrt = get_slrt(); |
| 263 | + |
| 264 | + policy = slr_get_policy(slrt); |
| 265 | + policy_entry = (struct slr_policy_entry *) |
| 266 | + ((uint8_t *)policy + sizeof(*policy)); |
| 267 | + |
| 268 | + measured = check_drtm_policy(slrt, policy, policy_entry, bi); |
| 269 | + for ( i = 0; i < measured; i++ ) |
| 270 | + policy_entry[i].flags |= SLR_POLICY_FLAG_MEASURED; |
| 271 | + |
| 272 | + for ( i = measured; i < policy->nr_entries; i++ ) |
| 273 | + { |
| 274 | + uint64_t start = policy_entry[i].entity; |
| 275 | + uint64_t size = policy_entry[i].size; |
| 276 | + |
| 277 | + /* No already measured entries are expected here. */ |
| 278 | + if ( policy_entry[i].flags & SLR_POLICY_FLAG_MEASURED ) |
| 279 | + panic("DRTM entry at %d was measured out of order!\n", i); |
| 280 | + |
| 281 | + switch ( policy_entry[i].entity_type ) |
| 282 | + { |
| 283 | + case SLR_ET_MULTIBOOT2_INFO: |
| 284 | + panic("Duplicated MBI entry in DRTM of Secure Launch at %d\n", i); |
| 285 | + case SLR_ET_SLRT: |
| 286 | + panic("Duplicated SLRT entry in DRTM of Secure Launch at %d\n", i); |
| 287 | + |
| 288 | + case SLR_ET_UNSPECIFIED: |
| 289 | + case SLR_ET_BOOT_PARAMS: |
| 290 | + case SLR_ET_SETUP_DATA: |
| 291 | + case SLR_ET_CMDLINE: |
| 292 | + case SLR_ET_UEFI_MEMMAP: |
| 293 | + case SLR_ET_RAMDISK: |
| 294 | + case SLR_ET_MULTIBOOT2_MODULE: |
| 295 | + case SLR_ET_TXT_OS2MLE: |
| 296 | + /* Measure this entry below. */ |
| 297 | + break; |
| 298 | + |
| 299 | + case SLR_ET_UNUSED: |
| 300 | + /* Skip this entry. */ |
| 301 | + continue; |
| 302 | + } |
| 303 | + |
| 304 | + if ( policy_entry[i].flags & SLR_POLICY_IMPLICIT_SIZE ) |
| 305 | + panic("Unexpected implicitly-sized DRTM entry of Secure Launch at %d (type %d, info: %s)\n", |
| 306 | + i, policy_entry[i].entity_type, policy_entry[i].evt_info); |
| 307 | + |
| 308 | + slaunch_map_l2(start, size); |
| 309 | + tpm_hash_extend(DRTM_LOC, policy_entry[i].pcr, __va(start), size, |
| 310 | + DLE_EVTYPE_SLAUNCH, (uint8_t *)policy_entry[i].evt_info, |
| 311 | + strnlen(policy_entry[i].evt_info, |
| 312 | + TPM_EVENT_INFO_LENGTH)); |
| 313 | + |
| 314 | + policy_entry[i].flags |= SLR_POLICY_FLAG_MEASURED; |
| 315 | + } |
| 316 | +} |
0 commit comments