Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/sev: Extend the config-fs attestation support for an SVSM

When an SVSM is present, the guest can also request attestation reports
from it. These SVSM attestation reports can be used to attest the SVSM
and any services running within the SVSM.

Extend the config-fs attestation support to provide such. This involves
creating four new config-fs attributes:

- 'service-provider' (input)
This attribute is used to determine whether the attestation request
should be sent to the specified service provider or to the SEV
firmware. The SVSM service provider is represented by the value
'svsm'.

- 'service_guid' (input)
Used for requesting the attestation of a single service within the
service provider. A null GUID implies that the SVSM_ATTEST_SERVICES
call should be used to request the attestation report. A non-null
GUID implies that the SVSM_ATTEST_SINGLE_SERVICE call should be used.

- 'service_manifest_version' (input)
Used with the SVSM_ATTEST_SINGLE_SERVICE call, the service version
represents a specific service manifest version be used for the
attestation report.

- 'manifestblob' (output)
Used to return the service manifest associated with the attestation
report.

Only display these new attributes when running under an SVSM.

[ bp: Massage.
- s/svsm_attestation_call/svsm_attest_call/g ]

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/965015dce3c76bb8724839d50c5dea4e4b5d598f.1717600736.git.thomas.lendacky@amd.com

authored by

Tom Lendacky and committed by
Borislav Petkov (AMD)
627dc671 20dfee95

+433 -3
+64
Documentation/ABI/testing/configfs-tsm
··· 31 31 Standardization v2.03 Section 4.1.8.1 MSG_REPORT_REQ. 32 32 https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf 33 33 34 + What: /sys/kernel/config/tsm/report/$name/manifestblob 35 + Date: January, 2024 36 + KernelVersion: v6.10 37 + Contact: linux-coco@lists.linux.dev 38 + Description: 39 + (RO) Optional supplemental data that a TSM may emit, visibility 40 + of this attribute depends on TSM, and may be empty if no 41 + manifest data is available. 42 + 43 + See 'service_provider' for information on the format of the 44 + manifest blob. 45 + 34 46 What: /sys/kernel/config/tsm/report/$name/provider 35 47 Date: September, 2023 36 48 KernelVersion: v6.7 ··· 92 80 Description: 93 81 (RO) Indicates the minimum permissible value that can be written 94 82 to @privlevel. 83 + 84 + What: /sys/kernel/config/tsm/report/$name/service_provider 85 + Date: January, 2024 86 + KernelVersion: v6.10 87 + Contact: linux-coco@lists.linux.dev 88 + Description: 89 + (WO) Attribute is visible if a TSM implementation provider 90 + supports the concept of attestation reports from a service 91 + provider for TVMs, like SEV-SNP running under an SVSM. 92 + Specifying the service provider via this attribute will create 93 + an attestation report as specified by the service provider. 94 + Currently supported service-providers are: 95 + svsm 96 + 97 + For the "svsm" service provider, see the Secure VM Service Module 98 + for SEV-SNP Guests v1.00 Section 7. For the doc, search for 99 + "site:amd.com "Secure VM Service Module for SEV-SNP 100 + Guests", docID: 58019" 101 + 102 + What: /sys/kernel/config/tsm/report/$name/service_guid 103 + Date: January, 2024 104 + KernelVersion: v6.10 105 + Contact: linux-coco@lists.linux.dev 106 + Description: 107 + (WO) Attribute is visible if a TSM implementation provider 108 + supports the concept of attestation reports from a service 109 + provider for TVMs, like SEV-SNP running under an SVSM. 110 + Specifying an empty/null GUID (00000000-0000-0000-0000-000000) 111 + requests all active services within the service provider be 112 + part of the attestation report. Specifying a GUID request 113 + an attestation report of just the specified service using the 114 + manifest form specified by the service_manifest_version 115 + attribute. 116 + 117 + See 'service_provider' for information on the format of the 118 + service guid. 119 + 120 + What: /sys/kernel/config/tsm/report/$name/service_manifest_version 121 + Date: January, 2024 122 + KernelVersion: v6.10 123 + Contact: linux-coco@lists.linux.dev 124 + Description: 125 + (WO) Attribute is visible if a TSM implementation provider 126 + supports the concept of attestation reports from a service 127 + provider for TVMs, like SEV-SNP running under an SVSM. 128 + Indicates the service manifest version requested for the 129 + attestation report (default 0). If this field is not set by 130 + the user, the default manifest version of the service (the 131 + service's initial/first manifest version) is returned. 132 + 133 + See 'service_provider' for information on the format of the 134 + service manifest version.
+30 -1
arch/x86/include/asm/sev.h
··· 214 214 sizeof(struct svsm_pvalidate_entry)) 215 215 216 216 /* 217 + * The SVSM Attestation related structures 218 + */ 219 + struct svsm_loc_entry { 220 + u64 pa; 221 + u32 len; 222 + u8 rsvd[4]; 223 + }; 224 + 225 + struct svsm_attest_call { 226 + struct svsm_loc_entry report_buf; 227 + struct svsm_loc_entry nonce; 228 + struct svsm_loc_entry manifest_buf; 229 + struct svsm_loc_entry certificates_buf; 230 + 231 + /* For attesting a single service */ 232 + u8 service_guid[16]; 233 + u32 service_manifest_ver; 234 + u8 rsvd[4]; 235 + }; 236 + 237 + /* 217 238 * SVSM protocol structure 218 239 */ 219 240 struct svsm_call { ··· 256 235 #define SVSM_CORE_PVALIDATE 1 257 236 #define SVSM_CORE_CREATE_VCPU 2 258 237 #define SVSM_CORE_DELETE_VCPU 3 238 + 239 + #define SVSM_ATTEST_CALL(x) ((1ULL << 32) | (x)) 240 + #define SVSM_ATTEST_SERVICES 0 241 + #define SVSM_ATTEST_SINGLE_SERVICE 1 259 242 260 243 #ifdef CONFIG_AMD_MEM_ENCRYPT 261 244 ··· 342 317 void __noreturn snp_abort(void); 343 318 void snp_dmi_setup(void); 344 319 int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio); 320 + int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input); 345 321 void snp_accept_memory(phys_addr_t start, phys_addr_t end); 346 322 u64 snp_get_unsupported_features(u64 status); 347 323 u64 sev_get_status(void); ··· 375 349 { 376 350 return -ENOTTY; 377 351 } 378 - 352 + static inline int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, struct svsm_attest_call *input) 353 + { 354 + return -ENOTTY; 355 + } 379 356 static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { } 380 357 static inline u64 snp_get_unsupported_features(u64 status) { return 0; } 381 358 static inline u64 sev_get_status(void) { return 0; }
+50
arch/x86/kernel/sev.c
··· 2387 2387 } 2388 2388 __setup("sev=", init_sev_config); 2389 2389 2390 + static void update_attest_input(struct svsm_call *call, struct svsm_attest_call *input) 2391 + { 2392 + /* If (new) lengths have been returned, propagate them up */ 2393 + if (call->rcx_out != call->rcx) 2394 + input->manifest_buf.len = call->rcx_out; 2395 + 2396 + if (call->rdx_out != call->rdx) 2397 + input->certificates_buf.len = call->rdx_out; 2398 + 2399 + if (call->r8_out != call->r8) 2400 + input->report_buf.len = call->r8_out; 2401 + } 2402 + 2403 + int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, 2404 + struct svsm_attest_call *input) 2405 + { 2406 + struct svsm_attest_call *ac; 2407 + unsigned long flags; 2408 + u64 attest_call_pa; 2409 + int ret; 2410 + 2411 + if (!snp_vmpl) 2412 + return -EINVAL; 2413 + 2414 + local_irq_save(flags); 2415 + 2416 + call->caa = svsm_get_caa(); 2417 + 2418 + ac = (struct svsm_attest_call *)call->caa->svsm_buffer; 2419 + attest_call_pa = svsm_get_caa_pa() + offsetof(struct svsm_ca, svsm_buffer); 2420 + 2421 + *ac = *input; 2422 + 2423 + /* 2424 + * Set input registers for the request and set RDX and R8 to known 2425 + * values in order to detect length values being returned in them. 2426 + */ 2427 + call->rax = call_id; 2428 + call->rcx = attest_call_pa; 2429 + call->rdx = -1; 2430 + call->r8 = -1; 2431 + ret = svsm_perform_call_protocol(call); 2432 + update_attest_input(call, input); 2433 + 2434 + local_irq_restore(flags); 2435 + 2436 + return ret; 2437 + } 2438 + EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req); 2439 + 2390 2440 int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) 2391 2441 { 2392 2442 struct ghcb_state state;
+179
drivers/virt/coco/sev-guest/sev-guest.c
··· 39 39 #define SNP_REQ_MAX_RETRY_DURATION (60*HZ) 40 40 #define SNP_REQ_RETRY_DELAY (2*HZ) 41 41 42 + #define SVSM_MAX_RETRIES 3 43 + 42 44 struct snp_guest_crypto { 43 45 struct crypto_aead *tfm; 44 46 u8 *iv, *authtag; ··· 793 791 u32 length; 794 792 }; 795 793 794 + static int sev_svsm_report_new(struct tsm_report *report, void *data) 795 + { 796 + unsigned int rep_len, man_len, certs_len; 797 + struct tsm_desc *desc = &report->desc; 798 + struct svsm_attest_call ac = {}; 799 + unsigned int retry_count; 800 + void *rep, *man, *certs; 801 + struct svsm_call call; 802 + unsigned int size; 803 + bool try_again; 804 + void *buffer; 805 + u64 call_id; 806 + int ret; 807 + 808 + /* 809 + * Allocate pages for the request: 810 + * - Report blob (4K) 811 + * - Manifest blob (4K) 812 + * - Certificate blob (16K) 813 + * 814 + * Above addresses must be 4K aligned 815 + */ 816 + rep_len = SZ_4K; 817 + man_len = SZ_4K; 818 + certs_len = SEV_FW_BLOB_MAX_SIZE; 819 + 820 + guard(mutex)(&snp_cmd_mutex); 821 + 822 + if (guid_is_null(&desc->service_guid)) { 823 + call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SERVICES); 824 + } else { 825 + export_guid(ac.service_guid, &desc->service_guid); 826 + ac.service_manifest_ver = desc->service_manifest_version; 827 + 828 + call_id = SVSM_ATTEST_CALL(SVSM_ATTEST_SINGLE_SERVICE); 829 + } 830 + 831 + retry_count = 0; 832 + 833 + retry: 834 + memset(&call, 0, sizeof(call)); 835 + 836 + size = rep_len + man_len + certs_len; 837 + buffer = alloc_pages_exact(size, __GFP_ZERO); 838 + if (!buffer) 839 + return -ENOMEM; 840 + 841 + rep = buffer; 842 + ac.report_buf.pa = __pa(rep); 843 + ac.report_buf.len = rep_len; 844 + 845 + man = rep + rep_len; 846 + ac.manifest_buf.pa = __pa(man); 847 + ac.manifest_buf.len = man_len; 848 + 849 + certs = man + man_len; 850 + ac.certificates_buf.pa = __pa(certs); 851 + ac.certificates_buf.len = certs_len; 852 + 853 + ac.nonce.pa = __pa(desc->inblob); 854 + ac.nonce.len = desc->inblob_len; 855 + 856 + ret = snp_issue_svsm_attest_req(call_id, &call, &ac); 857 + if (ret) { 858 + free_pages_exact(buffer, size); 859 + 860 + switch (call.rax_out) { 861 + case SVSM_ERR_INVALID_PARAMETER: 862 + try_again = false; 863 + 864 + if (ac.report_buf.len > rep_len) { 865 + rep_len = PAGE_ALIGN(ac.report_buf.len); 866 + try_again = true; 867 + } 868 + 869 + if (ac.manifest_buf.len > man_len) { 870 + man_len = PAGE_ALIGN(ac.manifest_buf.len); 871 + try_again = true; 872 + } 873 + 874 + if (ac.certificates_buf.len > certs_len) { 875 + certs_len = PAGE_ALIGN(ac.certificates_buf.len); 876 + try_again = true; 877 + } 878 + 879 + /* If one of the buffers wasn't large enough, retry the request */ 880 + if (try_again && retry_count < SVSM_MAX_RETRIES) { 881 + retry_count++; 882 + goto retry; 883 + } 884 + 885 + return -EINVAL; 886 + default: 887 + pr_err_ratelimited("SVSM attestation request failed (%d / 0x%llx)\n", 888 + ret, call.rax_out); 889 + return -EINVAL; 890 + } 891 + } 892 + 893 + /* 894 + * Allocate all the blob memory buffers at once so that the cleanup is 895 + * done for errors that occur after the first allocation (i.e. before 896 + * using no_free_ptr()). 897 + */ 898 + rep_len = ac.report_buf.len; 899 + void *rbuf __free(kvfree) = kvzalloc(rep_len, GFP_KERNEL); 900 + 901 + man_len = ac.manifest_buf.len; 902 + void *mbuf __free(kvfree) = kvzalloc(man_len, GFP_KERNEL); 903 + 904 + certs_len = ac.certificates_buf.len; 905 + void *cbuf __free(kvfree) = certs_len ? kvzalloc(certs_len, GFP_KERNEL) : NULL; 906 + 907 + if (!rbuf || !mbuf || (certs_len && !cbuf)) { 908 + free_pages_exact(buffer, size); 909 + return -ENOMEM; 910 + } 911 + 912 + memcpy(rbuf, rep, rep_len); 913 + report->outblob = no_free_ptr(rbuf); 914 + report->outblob_len = rep_len; 915 + 916 + memcpy(mbuf, man, man_len); 917 + report->manifestblob = no_free_ptr(mbuf); 918 + report->manifestblob_len = man_len; 919 + 920 + if (certs_len) { 921 + memcpy(cbuf, certs, certs_len); 922 + report->auxblob = no_free_ptr(cbuf); 923 + report->auxblob_len = certs_len; 924 + } 925 + 926 + free_pages_exact(buffer, size); 927 + 928 + return 0; 929 + } 930 + 796 931 static int sev_report_new(struct tsm_report *report, void *data) 797 932 { 798 933 struct snp_msg_cert_entry *cert_table; ··· 943 804 944 805 if (desc->inblob_len != SNP_REPORT_USER_DATA_SIZE) 945 806 return -EINVAL; 807 + 808 + if (desc->service_provider) { 809 + if (strcmp(desc->service_provider, "svsm")) 810 + return -EINVAL; 811 + 812 + return sev_svsm_report_new(report, data); 813 + } 946 814 947 815 void *buf __free(kvfree) = kvzalloc(size, GFP_KERNEL); 948 816 if (!buf) ··· 1039 893 return 0; 1040 894 } 1041 895 896 + static bool sev_report_attr_visible(int n) 897 + { 898 + switch (n) { 899 + case TSM_REPORT_GENERATION: 900 + case TSM_REPORT_PROVIDER: 901 + case TSM_REPORT_PRIVLEVEL: 902 + case TSM_REPORT_PRIVLEVEL_FLOOR: 903 + return true; 904 + case TSM_REPORT_SERVICE_PROVIDER: 905 + case TSM_REPORT_SERVICE_GUID: 906 + case TSM_REPORT_SERVICE_MANIFEST_VER: 907 + return snp_vmpl; 908 + } 909 + 910 + return false; 911 + } 912 + 913 + static bool sev_report_bin_attr_visible(int n) 914 + { 915 + switch (n) { 916 + case TSM_REPORT_INBLOB: 917 + case TSM_REPORT_OUTBLOB: 918 + case TSM_REPORT_AUXBLOB: 919 + return true; 920 + case TSM_REPORT_MANIFESTBLOB: 921 + return snp_vmpl; 922 + } 923 + 924 + return false; 925 + } 926 + 1042 927 static struct tsm_ops sev_tsm_ops = { 1043 928 .name = KBUILD_MODNAME, 1044 929 .report_new = sev_report_new, 930 + .report_attr_visible = sev_report_attr_visible, 931 + .report_bin_attr_visible = sev_report_bin_attr_visible, 1045 932 }; 1046 933 1047 934 static void unregister_sev_tsm(void *data)
+91 -2
drivers/virt/coco/tsm.c
··· 34 34 * The attestation report format is TSM provider specific, when / if a standard 35 35 * materializes that can be published instead of the vendor layout. Until then 36 36 * the 'provider' attribute indicates the format of 'outblob', and optionally 37 - * 'auxblob'. 37 + * 'auxblob' and 'manifestblob'. 38 38 */ 39 39 40 40 struct tsm_report_state { ··· 47 47 enum tsm_data_select { 48 48 TSM_REPORT, 49 49 TSM_CERTS, 50 + TSM_MANIFEST, 50 51 }; 51 52 52 53 static struct tsm_report *to_tsm_report(struct config_item *cfg) ··· 119 118 } 120 119 CONFIGFS_ATTR_RO(tsm_report_, privlevel_floor); 121 120 121 + static ssize_t tsm_report_service_provider_store(struct config_item *cfg, 122 + const char *buf, size_t len) 123 + { 124 + struct tsm_report *report = to_tsm_report(cfg); 125 + size_t sp_len; 126 + char *sp; 127 + int rc; 128 + 129 + guard(rwsem_write)(&tsm_rwsem); 130 + rc = try_advance_write_generation(report); 131 + if (rc) 132 + return rc; 133 + 134 + sp_len = (buf[len - 1] != '\n') ? len : len - 1; 135 + 136 + sp = kstrndup(buf, sp_len, GFP_KERNEL); 137 + if (!sp) 138 + return -ENOMEM; 139 + kfree(report->desc.service_provider); 140 + 141 + report->desc.service_provider = sp; 142 + 143 + return len; 144 + } 145 + CONFIGFS_ATTR_WO(tsm_report_, service_provider); 146 + 147 + static ssize_t tsm_report_service_guid_store(struct config_item *cfg, 148 + const char *buf, size_t len) 149 + { 150 + struct tsm_report *report = to_tsm_report(cfg); 151 + int rc; 152 + 153 + guard(rwsem_write)(&tsm_rwsem); 154 + rc = try_advance_write_generation(report); 155 + if (rc) 156 + return rc; 157 + 158 + report->desc.service_guid = guid_null; 159 + 160 + rc = guid_parse(buf, &report->desc.service_guid); 161 + if (rc) 162 + return rc; 163 + 164 + return len; 165 + } 166 + CONFIGFS_ATTR_WO(tsm_report_, service_guid); 167 + 168 + static ssize_t tsm_report_service_manifest_version_store(struct config_item *cfg, 169 + const char *buf, size_t len) 170 + { 171 + struct tsm_report *report = to_tsm_report(cfg); 172 + unsigned int val; 173 + int rc; 174 + 175 + rc = kstrtouint(buf, 0, &val); 176 + if (rc) 177 + return rc; 178 + 179 + guard(rwsem_write)(&tsm_rwsem); 180 + rc = try_advance_write_generation(report); 181 + if (rc) 182 + return rc; 183 + report->desc.service_manifest_version = val; 184 + 185 + return len; 186 + } 187 + CONFIGFS_ATTR_WO(tsm_report_, service_manifest_version); 188 + 122 189 static ssize_t tsm_report_inblob_write(struct config_item *cfg, 123 190 const void *buf, size_t count) 124 191 { ··· 231 162 if (select == TSM_REPORT) { 232 163 out = report->outblob; 233 164 len = report->outblob_len; 165 + } else if (select == TSM_MANIFEST) { 166 + out = report->manifestblob; 167 + len = report->manifestblob_len; 234 168 } else { 235 169 out = report->auxblob; 236 170 len = report->auxblob_len; ··· 259 187 260 188 /* 261 189 * A given TSM backend always fills in ->outblob regardless of 262 - * whether the report includes an auxblob or not. 190 + * whether the report includes an auxblob/manifestblob or not. 263 191 */ 264 192 if (!report->outblob || 265 193 state->read_generation != state->write_generation) ··· 295 223 296 224 kvfree(report->outblob); 297 225 kvfree(report->auxblob); 226 + kvfree(report->manifestblob); 298 227 report->outblob = NULL; 299 228 report->auxblob = NULL; 229 + report->manifestblob = NULL; 300 230 rc = ops->report_new(report, provider.data); 301 231 if (rc < 0) 302 232 return rc; ··· 325 251 } 326 252 CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_OUTBLOB_MAX); 327 253 254 + static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf, 255 + size_t count) 256 + { 257 + struct tsm_report *report = to_tsm_report(cfg); 258 + 259 + return tsm_report_read(report, buf, count, TSM_MANIFEST); 260 + } 261 + CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_OUTBLOB_MAX); 262 + 328 263 static struct configfs_attribute *tsm_report_attrs[] = { 329 264 [TSM_REPORT_GENERATION] = &tsm_report_attr_generation, 330 265 [TSM_REPORT_PROVIDER] = &tsm_report_attr_provider, 331 266 [TSM_REPORT_PRIVLEVEL] = &tsm_report_attr_privlevel, 332 267 [TSM_REPORT_PRIVLEVEL_FLOOR] = &tsm_report_attr_privlevel_floor, 268 + [TSM_REPORT_SERVICE_PROVIDER] = &tsm_report_attr_service_provider, 269 + [TSM_REPORT_SERVICE_GUID] = &tsm_report_attr_service_guid, 270 + [TSM_REPORT_SERVICE_MANIFEST_VER] = &tsm_report_attr_service_manifest_version, 333 271 NULL, 334 272 }; 335 273 ··· 349 263 [TSM_REPORT_INBLOB] = &tsm_report_attr_inblob, 350 264 [TSM_REPORT_OUTBLOB] = &tsm_report_attr_outblob, 351 265 [TSM_REPORT_AUXBLOB] = &tsm_report_attr_auxblob, 266 + [TSM_REPORT_MANIFESTBLOB] = &tsm_report_attr_manifestblob, 352 267 NULL, 353 268 }; 354 269 ··· 358 271 struct tsm_report *report = to_tsm_report(cfg); 359 272 struct tsm_report_state *state = to_state(report); 360 273 274 + kvfree(report->manifestblob); 361 275 kvfree(report->auxblob); 362 276 kvfree(report->outblob); 277 + kfree(report->desc.service_provider); 363 278 kfree(state); 364 279 } 365 280
+19
include/linux/tsm.h
··· 4 4 5 5 #include <linux/sizes.h> 6 6 #include <linux/types.h> 7 + #include <linux/uuid.h> 7 8 8 9 #define TSM_INBLOB_MAX 64 9 10 #define TSM_OUTBLOB_MAX SZ_32K ··· 20 19 * @privlevel: optional privilege level to associate with @outblob 21 20 * @inblob_len: sizeof @inblob 22 21 * @inblob: arbitrary input data 22 + * @service_provider: optional name of where to obtain the tsm report blob 23 + * @service_guid: optional service-provider service guid to attest 24 + * @service_manifest_version: optional service-provider service manifest version requested 23 25 */ 24 26 struct tsm_desc { 25 27 unsigned int privlevel; 26 28 size_t inblob_len; 27 29 u8 inblob[TSM_INBLOB_MAX]; 30 + char *service_provider; 31 + guid_t service_guid; 32 + unsigned int service_manifest_version; 28 33 }; 29 34 30 35 /** ··· 40 33 * @outblob: generated evidence to provider to the attestation agent 41 34 * @auxblob_len: sizeof(@auxblob) 42 35 * @auxblob: (optional) auxiliary data to the report (e.g. certificate data) 36 + * @manifestblob_len: sizeof(@manifestblob) 37 + * @manifestblob: (optional) manifest data associated with the report 43 38 */ 44 39 struct tsm_report { 45 40 struct tsm_desc desc; ··· 49 40 u8 *outblob; 50 41 size_t auxblob_len; 51 42 u8 *auxblob; 43 + size_t manifestblob_len; 44 + u8 *manifestblob; 52 45 }; 53 46 54 47 /** ··· 59 48 * @TSM_REPORT_PROVIDER: index of the provider name attribute 60 49 * @TSM_REPORT_PRIVLEVEL: index of the desired privilege level attribute 61 50 * @TSM_REPORT_PRIVLEVEL_FLOOR: index of the minimum allowed privileg level attribute 51 + * @TSM_REPORT_SERVICE_PROVIDER: index of the service provider identifier attribute 52 + * @TSM_REPORT_SERVICE_GUID: index of the service GUID attribute 53 + * @TSM_REPORT_SERVICE_MANIFEST_VER: index of the service manifest version attribute 62 54 */ 63 55 enum tsm_attr_index { 64 56 TSM_REPORT_GENERATION, 65 57 TSM_REPORT_PROVIDER, 66 58 TSM_REPORT_PRIVLEVEL, 67 59 TSM_REPORT_PRIVLEVEL_FLOOR, 60 + TSM_REPORT_SERVICE_PROVIDER, 61 + TSM_REPORT_SERVICE_GUID, 62 + TSM_REPORT_SERVICE_MANIFEST_VER, 68 63 }; 69 64 70 65 /** ··· 78 61 * @TSM_REPORT_INBLOB: index of the binary report input attribute 79 62 * @TSM_REPORT_OUTBLOB: index of the binary report output attribute 80 63 * @TSM_REPORT_AUXBLOB: index of the binary auxiliary data attribute 64 + * @TSM_REPORT_MANIFESTBLOB: index of the binary manifest data attribute 81 65 */ 82 66 enum tsm_bin_attr_index { 83 67 TSM_REPORT_INBLOB, 84 68 TSM_REPORT_OUTBLOB, 85 69 TSM_REPORT_AUXBLOB, 70 + TSM_REPORT_MANIFESTBLOB, 86 71 }; 87 72 88 73 /**