]> Git Repo - qemu.git/blame - target/i386/sev.c
target/i386/sev: Rephrase error message when no hashes table in guest firmware
[qemu.git] / target / i386 / sev.c
CommitLineData
a9b4942f
BS
1/*
2 * QEMU SEV support
3 *
4 * Copyright Advanced Micro Devices 2016-2018
5 *
6 * Author:
7 * Brijesh Singh <[email protected]>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 *
12 */
13
b7d89466
MA
14#include "qemu/osdep.h"
15
d8575c6c
BS
16#include <linux/kvm.h>
17#include <linux/psp-sev.h>
18
19#include <sys/ioctl.h>
20
a9b4942f
BS
21#include "qapi/error.h"
22#include "qom/object_interfaces.h"
23#include "qemu/base64.h"
0b8fa32f 24#include "qemu/module.h"
b2f73a07 25#include "qemu/uuid.h"
cff03145 26#include "crypto/hash.h"
a9b4942f 27#include "sysemu/kvm.h"
93777de3 28#include "sev.h"
a9b4942f 29#include "sysemu/sysemu.h"
54d31236 30#include "sysemu/runstate.h"
d8575c6c 31#include "trace.h"
8fa4466d 32#include "migration/blocker.h"
db1015e9 33#include "qom/object.h"
c7f7e697 34#include "monitor/monitor.h"
cd35beb4 35#include "monitor/hmp-target.h"
3208de1c
PMD
36#include "qapi/qapi-commands-misc-target.h"
37#include "qapi/qmp/qerror.h"
f91f9f25 38#include "exec/confidential-guest-support.h"
b2f73a07 39#include "hw/i386/pc.h"
a9b4942f 40
d2d8a198 41#define TYPE_SEV_GUEST "sev-guest"
8063396b 42OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
a86ab19d 43
a86ab19d
DG
44
45/**
d2d8a198 46 * SevGuestState:
a86ab19d 47 *
d2d8a198
DG
48 * The SevGuestState object is used for creating and managing a SEV
49 * guest.
a86ab19d
DG
50 *
51 * # $QEMU \
52 * -object sev-guest,id=sev0 \
53 * -machine ...,memory-encryption=sev0
54 */
d2d8a198 55struct SevGuestState {
f91f9f25 56 ConfidentialGuestSupport parent_obj;
a86ab19d 57
75a877e3 58 /* configuration parameters */
a86ab19d
DG
59 char *sev_device;
60 uint32_t policy;
a86ab19d
DG
61 char *dh_cert_file;
62 char *session_file;
63 uint32_t cbitpos;
64 uint32_t reduced_phys_bits;
55cdf566 65 bool kernel_hashes;
a86ab19d 66
75a877e3 67 /* runtime state */
cf504cd6 68 uint32_t handle;
421522eb
DG
69 uint8_t api_major;
70 uint8_t api_minor;
71 uint8_t build_id;
421522eb
DG
72 int sev_fd;
73 SevState state;
74 gchar *measurement;
b2f73a07
PB
75
76 uint32_t reset_cs;
77 uint32_t reset_ip;
78 bool reset_data_valid;
a86ab19d
DG
79};
80
a9b4942f
BS
81#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
82#define DEFAULT_SEV_DEVICE "/dev/sev"
83
b2f73a07
PB
84#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
85typedef struct __attribute__((__packed__)) SevInfoBlock {
86 /* SEV-ES Reset Vector Address */
87 uint32_t reset_addr;
88} SevInfoBlock;
89
cff03145
DM
90#define SEV_HASH_TABLE_RV_GUID "7255371f-3a3b-4b04-927b-1da6efa8d454"
91typedef struct QEMU_PACKED SevHashTableDescriptor {
92 /* SEV hash table area guest address */
93 uint32_t base;
94 /* SEV hash table area size (in bytes) */
95 uint32_t size;
96} SevHashTableDescriptor;
97
98/* hard code sha256 digest size */
99#define HASH_SIZE 32
100
101typedef struct QEMU_PACKED SevHashTableEntry {
102 QemuUUID guid;
103 uint16_t len;
104 uint8_t hash[HASH_SIZE];
105} SevHashTableEntry;
106
107typedef struct QEMU_PACKED SevHashTable {
108 QemuUUID guid;
109 uint16_t len;
110 SevHashTableEntry cmdline;
111 SevHashTableEntry initrd;
112 SevHashTableEntry kernel;
113 uint8_t padding[];
114} SevHashTable;
115
8673dee3 116static SevGuestState *sev_guest;
8fa4466d 117static Error *sev_mig_blocker;
d8575c6c
BS
118
119static const char *const sev_fw_errlist[] = {
5811b936
CK
120 [SEV_RET_SUCCESS] = "",
121 [SEV_RET_INVALID_PLATFORM_STATE] = "Platform state is invalid",
122 [SEV_RET_INVALID_GUEST_STATE] = "Guest state is invalid",
123 [SEV_RET_INAVLID_CONFIG] = "Platform configuration is invalid",
124 [SEV_RET_INVALID_LEN] = "Buffer too small",
125 [SEV_RET_ALREADY_OWNED] = "Platform is already owned",
126 [SEV_RET_INVALID_CERTIFICATE] = "Certificate is invalid",
127 [SEV_RET_POLICY_FAILURE] = "Policy is not allowed",
128 [SEV_RET_INACTIVE] = "Guest is not active",
129 [SEV_RET_INVALID_ADDRESS] = "Invalid address",
130 [SEV_RET_BAD_SIGNATURE] = "Bad signature",
131 [SEV_RET_BAD_MEASUREMENT] = "Bad measurement",
132 [SEV_RET_ASID_OWNED] = "ASID is already owned",
133 [SEV_RET_INVALID_ASID] = "Invalid ASID",
134 [SEV_RET_WBINVD_REQUIRED] = "WBINVD is required",
135 [SEV_RET_DFFLUSH_REQUIRED] = "DF_FLUSH is required",
136 [SEV_RET_INVALID_GUEST] = "Guest handle is invalid",
137 [SEV_RET_INVALID_COMMAND] = "Invalid command",
138 [SEV_RET_ACTIVE] = "Guest is active",
139 [SEV_RET_HWSEV_RET_PLATFORM] = "Hardware error",
140 [SEV_RET_HWSEV_RET_UNSAFE] = "Hardware unsafe",
141 [SEV_RET_UNSUPPORTED] = "Feature not supported",
142 [SEV_RET_INVALID_PARAM] = "Invalid parameter",
d47b8550
CK
143 [SEV_RET_RESOURCE_LIMIT] = "Required firmware resource depleted",
144 [SEV_RET_SECURE_DATA_INVALID] = "Part-specific integrity check failure",
d8575c6c
BS
145};
146
147#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
148
149static int
150sev_ioctl(int fd, int cmd, void *data, int *error)
151{
152 int r;
153 struct kvm_sev_cmd input;
154
155 memset(&input, 0x0, sizeof(input));
156
157 input.id = cmd;
158 input.sev_fd = fd;
159 input.data = (__u64)(unsigned long)data;
160
161 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
162
163 if (error) {
164 *error = input.error;
165 }
166
167 return r;
168}
169
170static int
171sev_platform_ioctl(int fd, int cmd, void *data, int *error)
172{
173 int r;
174 struct sev_issue_cmd arg;
175
176 arg.cmd = cmd;
177 arg.data = (unsigned long)data;
178 r = ioctl(fd, SEV_ISSUE_CMD, &arg);
179 if (error) {
180 *error = arg.error;
181 }
182
183 return r;
184}
185
186static const char *
187fw_error_to_str(int code)
188{
189 if (code < 0 || code >= SEV_FW_MAX_ERROR) {
190 return "unknown error";
191 }
192
193 return sev_fw_errlist[code];
194}
195
b738d630 196static bool
8673dee3 197sev_check_state(const SevGuestState *sev, SevState state)
b738d630 198{
8673dee3 199 assert(sev);
421522eb 200 return sev->state == state ? true : false;
b738d630
BS
201}
202
620fd55c 203static void
8673dee3 204sev_set_guest_state(SevGuestState *sev, SevState new_state)
620fd55c
BS
205{
206 assert(new_state < SEV_STATE__MAX);
8673dee3 207 assert(sev);
620fd55c 208
421522eb 209 trace_kvm_sev_change_state(SevState_str(sev->state),
620fd55c 210 SevState_str(new_state));
421522eb 211 sev->state = new_state;
620fd55c
BS
212}
213
2b308e44 214static void
8f44304c
DH
215sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
216 size_t max_size)
2b308e44
BS
217{
218 int r;
219 struct kvm_enc_region range;
cedc0ad5
BS
220 ram_addr_t offset;
221 MemoryRegion *mr;
222
223 /*
224 * The RAM device presents a memory region that should be treated
225 * as IO region and should not be pinned.
226 */
227 mr = memory_region_from_host(host, &offset);
228 if (mr && memory_region_is_ram_device(mr)) {
229 return;
230 }
2b308e44
BS
231
232 range.addr = (__u64)(unsigned long)host;
8f44304c 233 range.size = max_size;
2b308e44 234
8f44304c 235 trace_kvm_memcrypt_register_region(host, max_size);
2b308e44
BS
236 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
237 if (r) {
238 error_report("%s: failed to register region (%p+%#zx) error '%s'",
8f44304c 239 __func__, host, max_size, strerror(errno));
2b308e44
BS
240 exit(1);
241 }
242}
243
244static void
8f44304c
DH
245sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size,
246 size_t max_size)
2b308e44
BS
247{
248 int r;
249 struct kvm_enc_region range;
56e2ec94
AW
250 ram_addr_t offset;
251 MemoryRegion *mr;
252
253 /*
254 * The RAM device presents a memory region that should be treated
255 * as IO region and should not have been pinned.
256 */
257 mr = memory_region_from_host(host, &offset);
258 if (mr && memory_region_is_ram_device(mr)) {
259 return;
260 }
2b308e44
BS
261
262 range.addr = (__u64)(unsigned long)host;
8f44304c 263 range.size = max_size;
2b308e44 264
8f44304c 265 trace_kvm_memcrypt_unregister_region(host, max_size);
2b308e44
BS
266 r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
267 if (r) {
268 error_report("%s: failed to unregister region (%p+%#zx)",
8f44304c 269 __func__, host, max_size);
2b308e44
BS
270 }
271}
272
273static struct RAMBlockNotifier sev_ram_notifier = {
274 .ram_block_added = sev_ram_block_added,
275 .ram_block_removed = sev_ram_block_removed,
276};
277
a9b4942f 278static void
d2d8a198 279sev_guest_finalize(Object *obj)
a9b4942f
BS
280{
281}
282
283static char *
d2d8a198 284sev_guest_get_session_file(Object *obj, Error **errp)
a9b4942f 285{
d2d8a198 286 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
287
288 return s->session_file ? g_strdup(s->session_file) : NULL;
289}
290
291static void
d2d8a198 292sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
a9b4942f 293{
d2d8a198 294 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
295
296 s->session_file = g_strdup(value);
297}
298
299static char *
d2d8a198 300sev_guest_get_dh_cert_file(Object *obj, Error **errp)
a9b4942f 301{
d2d8a198 302 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
303
304 return g_strdup(s->dh_cert_file);
305}
306
307static void
d2d8a198 308sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
a9b4942f 309{
d2d8a198 310 SevGuestState *s = SEV_GUEST(obj);
a9b4942f
BS
311
312 s->dh_cert_file = g_strdup(value);
313}
314
315static char *
d2d8a198 316sev_guest_get_sev_device(Object *obj, Error **errp)
a9b4942f 317{
d2d8a198 318 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
319
320 return g_strdup(sev->sev_device);
321}
322
323static void
d2d8a198 324sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
a9b4942f 325{
d2d8a198 326 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
327
328 sev->sev_device = g_strdup(value);
329}
330
55cdf566
DM
331static bool sev_guest_get_kernel_hashes(Object *obj, Error **errp)
332{
333 SevGuestState *sev = SEV_GUEST(obj);
334
335 return sev->kernel_hashes;
336}
337
338static void sev_guest_set_kernel_hashes(Object *obj, bool value, Error **errp)
339{
340 SevGuestState *sev = SEV_GUEST(obj);
341
342 sev->kernel_hashes = value;
343}
344
a9b4942f 345static void
d2d8a198 346sev_guest_class_init(ObjectClass *oc, void *data)
a9b4942f
BS
347{
348 object_class_property_add_str(oc, "sev-device",
d2d8a198
DG
349 sev_guest_get_sev_device,
350 sev_guest_set_sev_device);
a9b4942f 351 object_class_property_set_description(oc, "sev-device",
7eecec7d 352 "SEV device to use");
a9b4942f 353 object_class_property_add_str(oc, "dh-cert-file",
d2d8a198
DG
354 sev_guest_get_dh_cert_file,
355 sev_guest_set_dh_cert_file);
a9b4942f 356 object_class_property_set_description(oc, "dh-cert-file",
7eecec7d 357 "guest owners DH certificate (encoded with base64)");
a9b4942f 358 object_class_property_add_str(oc, "session-file",
d2d8a198
DG
359 sev_guest_get_session_file,
360 sev_guest_set_session_file);
a9b4942f 361 object_class_property_set_description(oc, "session-file",
7eecec7d 362 "guest owners session parameters (encoded with base64)");
55cdf566
DM
363 object_class_property_add_bool(oc, "kernel-hashes",
364 sev_guest_get_kernel_hashes,
365 sev_guest_set_kernel_hashes);
366 object_class_property_set_description(oc, "kernel-hashes",
367 "add kernel hashes to guest firmware for measured Linux boot");
a9b4942f
BS
368}
369
a9b4942f 370static void
d2d8a198 371sev_guest_instance_init(Object *obj)
a9b4942f 372{
d2d8a198 373 SevGuestState *sev = SEV_GUEST(obj);
a9b4942f
BS
374
375 sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
376 sev->policy = DEFAULT_GUEST_POLICY;
64a7b8de 377 object_property_add_uint32_ptr(obj, "policy", &sev->policy,
d2623129 378 OBJ_PROP_FLAG_READWRITE);
64a7b8de 379 object_property_add_uint32_ptr(obj, "handle", &sev->handle,
d2623129 380 OBJ_PROP_FLAG_READWRITE);
64a7b8de 381 object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
d2623129 382 OBJ_PROP_FLAG_READWRITE);
64a7b8de
FF
383 object_property_add_uint32_ptr(obj, "reduced-phys-bits",
384 &sev->reduced_phys_bits,
d2623129 385 OBJ_PROP_FLAG_READWRITE);
a9b4942f
BS
386}
387
388/* sev guest info */
d2d8a198 389static const TypeInfo sev_guest_info = {
f91f9f25 390 .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
d2d8a198
DG
391 .name = TYPE_SEV_GUEST,
392 .instance_size = sizeof(SevGuestState),
393 .instance_finalize = sev_guest_finalize,
394 .class_init = sev_guest_class_init,
395 .instance_init = sev_guest_instance_init,
a9b4942f
BS
396 .interfaces = (InterfaceInfo[]) {
397 { TYPE_USER_CREATABLE },
398 { }
399 }
400};
401
d8575c6c
BS
402bool
403sev_enabled(void)
404{
8673dee3 405 return !!sev_guest;
d8575c6c
BS
406}
407
6b98e96f
TL
408bool
409sev_es_enabled(void)
410{
027b524d 411 return sev_enabled() && (sev_guest->policy & SEV_POLICY_ES);
6b98e96f
TL
412}
413
d8575c6c
BS
414uint32_t
415sev_get_cbit_position(void)
416{
a06d2bad 417 return sev_guest ? sev_guest->cbitpos : 0;
d8575c6c
BS
418}
419
420uint32_t
421sev_get_reduced_phys_bits(void)
422{
a06d2bad 423 return sev_guest ? sev_guest->reduced_phys_bits : 0;
d8575c6c
BS
424}
425
aa395018 426static SevInfo *sev_get_info(void)
d8575c6c
BS
427{
428 SevInfo *info;
429
430 info = g_new0(SevInfo, 1);
8673dee3 431 info->enabled = sev_enabled();
d8575c6c
BS
432
433 if (info->enabled) {
421522eb
DG
434 info->api_major = sev_guest->api_major;
435 info->api_minor = sev_guest->api_minor;
436 info->build_id = sev_guest->build_id;
0bd15277 437 info->policy = sev_guest->policy;
421522eb 438 info->state = sev_guest->state;
cf504cd6 439 info->handle = sev_guest->handle;
d8575c6c
BS
440 }
441
442 return info;
443}
444
aa395018
PMD
445SevInfo *qmp_query_sev(Error **errp)
446{
447 SevInfo *info;
448
449 info = sev_get_info();
450 if (!info) {
451 error_setg(errp, "SEV feature is not available");
452 return NULL;
453 }
454
455 return info;
456}
457
458void hmp_info_sev(Monitor *mon, const QDict *qdict)
459{
460 SevInfo *info = sev_get_info();
461
462 if (info && info->enabled) {
463 monitor_printf(mon, "handle: %d\n", info->handle);
464 monitor_printf(mon, "state: %s\n", SevState_str(info->state));
465 monitor_printf(mon, "build: %d\n", info->build_id);
466 monitor_printf(mon, "api version: %d.%d\n",
467 info->api_major, info->api_minor);
468 monitor_printf(mon, "debug: %s\n",
469 info->policy & SEV_POLICY_NODBG ? "off" : "on");
470 monitor_printf(mon, "key-sharing: %s\n",
471 info->policy & SEV_POLICY_NOKS ? "off" : "on");
472 } else {
473 monitor_printf(mon, "SEV is not enabled\n");
474 }
475
476 qapi_free_SevInfo(info);
477}
478
9f750794
BS
479static int
480sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
e4f62785 481 size_t *cert_chain_len, Error **errp)
9f750794 482{
bf3175b4
PB
483 guchar *pdh_data = NULL;
484 guchar *cert_chain_data = NULL;
9f750794
BS
485 struct sev_user_data_pdh_cert_export export = {};
486 int err, r;
487
488 /* query the certificate length */
489 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
490 if (r < 0) {
491 if (err != SEV_RET_INVALID_LEN) {
2c7233eb
PMD
492 error_setg(errp, "SEV: Failed to export PDH cert"
493 " ret=%d fw_err=%d (%s)",
e4f62785 494 r, err, fw_error_to_str(err));
9f750794
BS
495 return 1;
496 }
497 }
498
499 pdh_data = g_new(guchar, export.pdh_cert_len);
500 cert_chain_data = g_new(guchar, export.cert_chain_len);
501 export.pdh_cert_address = (unsigned long)pdh_data;
502 export.cert_chain_address = (unsigned long)cert_chain_data;
503
504 r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
505 if (r < 0) {
2c7233eb 506 error_setg(errp, "SEV: Failed to export PDH cert ret=%d fw_err=%d (%s)",
e4f62785 507 r, err, fw_error_to_str(err));
9f750794
BS
508 goto e_free;
509 }
510
511 *pdh = pdh_data;
512 *pdh_len = export.pdh_cert_len;
513 *cert_chain = cert_chain_data;
514 *cert_chain_len = export.cert_chain_len;
515 return 0;
516
517e_free:
518 g_free(pdh_data);
519 g_free(cert_chain_data);
520 return 1;
521}
522
8371df29 523static SevCapability *sev_get_capabilities(Error **errp)
9f750794 524{
bf3175b4
PB
525 SevCapability *cap = NULL;
526 guchar *pdh_data = NULL;
527 guchar *cert_chain_data = NULL;
9f750794
BS
528 size_t pdh_len = 0, cert_chain_len = 0;
529 uint32_t ebx;
530 int fd;
531
1b38750c
PB
532 if (!kvm_enabled()) {
533 error_setg(errp, "KVM not enabled");
534 return NULL;
535 }
536 if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
537 error_setg(errp, "SEV is not enabled in KVM");
538 return NULL;
539 }
540
9f750794
BS
541 fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
542 if (fd < 0) {
2c7233eb 543 error_setg_errno(errp, errno, "SEV: Failed to open %s",
e4f62785 544 DEFAULT_SEV_DEVICE);
9f750794
BS
545 return NULL;
546 }
547
548 if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
e4f62785 549 &cert_chain_data, &cert_chain_len, errp)) {
bf3175b4 550 goto out;
9f750794
BS
551 }
552
553 cap = g_new0(SevCapability, 1);
554 cap->pdh = g_base64_encode(pdh_data, pdh_len);
555 cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
556
557 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
558 cap->cbitpos = ebx & 0x3f;
559
560 /*
561 * When SEV feature is enabled, we loose one bit in guest physical
562 * addressing.
563 */
564 cap->reduced_phys_bits = 1;
565
bf3175b4 566out:
9f750794
BS
567 g_free(pdh_data);
568 g_free(cert_chain_data);
9f750794
BS
569 close(fd);
570 return cap;
571}
572
8371df29
PMD
573SevCapability *qmp_query_sev_capabilities(Error **errp)
574{
575 return sev_get_capabilities(errp);
576}
577
3208de1c
PMD
578static SevAttestationReport *sev_get_attestation_report(const char *mnonce,
579 Error **errp)
3ea1a802
BS
580{
581 struct kvm_sev_attestation_report input = {};
582 SevAttestationReport *report = NULL;
583 SevGuestState *sev = sev_guest;
ed84ae72
DDAG
584 g_autofree guchar *data = NULL;
585 g_autofree guchar *buf = NULL;
3ea1a802
BS
586 gsize len;
587 int err = 0, ret;
588
589 if (!sev_enabled()) {
590 error_setg(errp, "SEV is not enabled");
591 return NULL;
592 }
593
594 /* lets decode the mnonce string */
595 buf = g_base64_decode(mnonce, &len);
596 if (!buf) {
597 error_setg(errp, "SEV: failed to decode mnonce input");
598 return NULL;
599 }
600
601 /* verify the input mnonce length */
602 if (len != sizeof(input.mnonce)) {
603 error_setg(errp, "SEV: mnonce must be %zu bytes (got %" G_GSIZE_FORMAT ")",
604 sizeof(input.mnonce), len);
3ea1a802
BS
605 return NULL;
606 }
607
608 /* Query the report length */
609 ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
610 &input, &err);
611 if (ret < 0) {
612 if (err != SEV_RET_INVALID_LEN) {
2c7233eb
PMD
613 error_setg(errp, "SEV: Failed to query the attestation report"
614 " length ret=%d fw_err=%d (%s)",
615 ret, err, fw_error_to_str(err));
3ea1a802
BS
616 return NULL;
617 }
618 }
619
620 data = g_malloc(input.len);
621 input.uaddr = (unsigned long)data;
622 memcpy(input.mnonce, buf, sizeof(input.mnonce));
623
624 /* Query the report */
625 ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
626 &input, &err);
627 if (ret) {
2c7233eb 628 error_setg_errno(errp, errno, "SEV: Failed to get attestation report"
3ea1a802 629 " ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
ed84ae72 630 return NULL;
3ea1a802
BS
631 }
632
633 report = g_new0(SevAttestationReport, 1);
634 report->data = g_base64_encode(data, input.len);
635
636 trace_kvm_sev_attestation_report(mnonce, report->data);
637
3ea1a802
BS
638 return report;
639}
640
3208de1c
PMD
641SevAttestationReport *qmp_query_sev_attestation_report(const char *mnonce,
642 Error **errp)
643{
644 return sev_get_attestation_report(mnonce, errp);
645}
646
620fd55c
BS
647static int
648sev_read_file_base64(const char *filename, guchar **data, gsize *len)
649{
650 gsize sz;
523a3d95 651 g_autofree gchar *base64 = NULL;
620fd55c
BS
652 GError *error = NULL;
653
654 if (!g_file_get_contents(filename, &base64, &sz, &error)) {
2c7233eb 655 error_report("SEV: Failed to read '%s' (%s)", filename, error->message);
efacd5b8 656 g_error_free(error);
620fd55c
BS
657 return -1;
658 }
659
660 *data = g_base64_decode(base64, len);
661 return 0;
662}
663
664static int
75a877e3 665sev_launch_start(SevGuestState *sev)
620fd55c
BS
666{
667 gsize sz;
668 int ret = 1;
bf3175b4 669 int fw_error, rc;
eb8257a2
DM
670 struct kvm_sev_launch_start start = {
671 .handle = sev->handle, .policy = sev->policy
672 };
620fd55c
BS
673 guchar *session = NULL, *dh_cert = NULL;
674
620fd55c
BS
675 if (sev->session_file) {
676 if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
bf3175b4 677 goto out;
620fd55c 678 }
eb8257a2
DM
679 start.session_uaddr = (unsigned long)session;
680 start.session_len = sz;
620fd55c
BS
681 }
682
683 if (sev->dh_cert_file) {
684 if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
bf3175b4 685 goto out;
620fd55c 686 }
eb8257a2
DM
687 start.dh_uaddr = (unsigned long)dh_cert;
688 start.dh_len = sz;
620fd55c
BS
689 }
690
eb8257a2
DM
691 trace_kvm_sev_launch_start(start.policy, session, dh_cert);
692 rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, &start, &fw_error);
bf3175b4 693 if (rc < 0) {
620fd55c
BS
694 error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
695 __func__, ret, fw_error, fw_error_to_str(fw_error));
bf3175b4 696 goto out;
620fd55c
BS
697 }
698
8673dee3 699 sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
eb8257a2 700 sev->handle = start.handle;
bf3175b4 701 ret = 0;
620fd55c 702
bf3175b4 703out:
620fd55c
BS
704 g_free(session);
705 g_free(dh_cert);
bf3175b4 706 return ret;
620fd55c
BS
707}
708
b738d630 709static int
8673dee3 710sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
b738d630
BS
711{
712 int ret, fw_error;
713 struct kvm_sev_launch_update_data update;
714
715 if (!addr || !len) {
716 return 1;
717 }
718
719 update.uaddr = (__u64)(unsigned long)addr;
720 update.len = len;
721 trace_kvm_sev_launch_update_data(addr, len);
421522eb 722 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
b738d630
BS
723 &update, &fw_error);
724 if (ret) {
725 error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
726 __func__, ret, fw_error, fw_error_to_str(fw_error));
727 }
728
729 return ret;
730}
731
6b98e96f
TL
732static int
733sev_launch_update_vmsa(SevGuestState *sev)
734{
735 int ret, fw_error;
736
737 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fw_error);
738 if (ret) {
739 error_report("%s: LAUNCH_UPDATE_VMSA ret=%d fw_error=%d '%s'",
740 __func__, ret, fw_error, fw_error_to_str(fw_error));
741 }
742
743 return ret;
744}
745
c6c89c97
BS
746static void
747sev_launch_get_measure(Notifier *notifier, void *unused)
748{
8673dee3 749 SevGuestState *sev = sev_guest;
c6c89c97 750 int ret, error;
2f573c41 751 g_autofree guchar *data = NULL;
59e42d88 752 struct kvm_sev_launch_measure measurement = {};
c6c89c97 753
8673dee3 754 if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
c6c89c97
BS
755 return;
756 }
757
6b98e96f
TL
758 if (sev_es_enabled()) {
759 /* measure all the VM save areas before getting launch_measure */
760 ret = sev_launch_update_vmsa(sev);
761 if (ret) {
762 exit(1);
763 }
764 }
765
c6c89c97 766 /* query the measurement blob length */
421522eb 767 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
59e42d88
DM
768 &measurement, &error);
769 if (!measurement.len) {
c6c89c97
BS
770 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
771 __func__, ret, error, fw_error_to_str(errno));
2f573c41 772 return;
c6c89c97
BS
773 }
774
59e42d88
DM
775 data = g_new0(guchar, measurement.len);
776 measurement.uaddr = (unsigned long)data;
c6c89c97
BS
777
778 /* get the measurement blob */
421522eb 779 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
59e42d88 780 &measurement, &error);
c6c89c97
BS
781 if (ret) {
782 error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
783 __func__, ret, error, fw_error_to_str(errno));
2f573c41 784 return;
c6c89c97
BS
785 }
786
8673dee3 787 sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
c6c89c97
BS
788
789 /* encode the measurement value and emit the event */
59e42d88 790 sev->measurement = g_base64_encode(data, measurement.len);
421522eb 791 trace_kvm_sev_launch_measurement(sev->measurement);
c6c89c97
BS
792}
793
0875a703 794static char *sev_get_launch_measurement(void)
c6c89c97 795{
8673dee3 796 if (sev_guest &&
421522eb
DG
797 sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
798 return g_strdup(sev_guest->measurement);
c6c89c97
BS
799 }
800
801 return NULL;
802}
803
0875a703
PMD
804SevLaunchMeasureInfo *qmp_query_sev_launch_measure(Error **errp)
805{
806 char *data;
807 SevLaunchMeasureInfo *info;
808
809 data = sev_get_launch_measurement();
810 if (!data) {
811 error_setg(errp, "SEV launch measurement is not available");
812 return NULL;
813 }
814
815 info = g_malloc0(sizeof(*info));
816 info->data = data;
817
818 return info;
819}
820
c6c89c97
BS
821static Notifier sev_machine_done_notify = {
822 .notify = sev_launch_get_measure,
823};
824
5dd0df7e 825static void
8673dee3 826sev_launch_finish(SevGuestState *sev)
5dd0df7e
BS
827{
828 int ret, error;
829
830 trace_kvm_sev_launch_finish();
421522eb 831 ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
5dd0df7e
BS
832 if (ret) {
833 error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
834 __func__, ret, error, fw_error_to_str(error));
835 exit(1);
836 }
837
8673dee3 838 sev_set_guest_state(sev, SEV_STATE_RUNNING);
8fa4466d
BS
839
840 /* add migration blocker */
841 error_setg(&sev_mig_blocker,
842 "SEV: Migration is not implemented");
f9734d5d 843 migrate_add_blocker(sev_mig_blocker, &error_fatal);
5dd0df7e
BS
844}
845
846static void
538f0497 847sev_vm_state_change(void *opaque, bool running, RunState state)
5dd0df7e 848{
8673dee3 849 SevGuestState *sev = opaque;
5dd0df7e
BS
850
851 if (running) {
8673dee3
DG
852 if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
853 sev_launch_finish(sev);
5dd0df7e
BS
854 }
855 }
856}
857
c9f5aaa6 858int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
d8575c6c 859{
ec78e2cd
DG
860 SevGuestState *sev
861 = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
d8575c6c 862 char *devname;
6b98e96f 863 int ret, fw_error, cmd;
d8575c6c
BS
864 uint32_t ebx;
865 uint32_t host_cbitpos;
866 struct sev_user_data_status status = {};
867
ec78e2cd
DG
868 if (!sev) {
869 return 0;
870 }
871
fee3f3ba
DH
872 ret = ram_block_discard_disable(true);
873 if (ret) {
874 error_report("%s: cannot disable RAM discard", __func__);
aacdb844 875 return -1;
fee3f3ba
DH
876 }
877
8673dee3 878 sev_guest = sev;
421522eb 879 sev->state = SEV_STATE_UNINIT;
d8575c6c
BS
880
881 host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
882 host_cbitpos = ebx & 0x3f;
883
a06d2bad 884 if (host_cbitpos != sev->cbitpos) {
c9f5aaa6
DG
885 error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
886 __func__, host_cbitpos, sev->cbitpos);
d8575c6c
BS
887 goto err;
888 }
889
a06d2bad 890 if (sev->reduced_phys_bits < 1) {
c9f5aaa6
DG
891 error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
892 " requested '%d'", __func__, sev->reduced_phys_bits);
d8575c6c
BS
893 goto err;
894 }
895
75a877e3 896 devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
421522eb
DG
897 sev->sev_fd = open(devname, O_RDWR);
898 if (sev->sev_fd < 0) {
c9f5aaa6
DG
899 error_setg(errp, "%s: Failed to open %s '%s'", __func__,
900 devname, strerror(errno));
901 g_free(devname);
5d7bc72a
GK
902 goto err;
903 }
c9f5aaa6 904 g_free(devname);
d8575c6c 905
421522eb 906 ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
d8575c6c
BS
907 &fw_error);
908 if (ret) {
c9f5aaa6
DG
909 error_setg(errp, "%s: failed to get platform status ret=%d "
910 "fw_error='%d: %s'", __func__, ret, fw_error,
911 fw_error_to_str(fw_error));
d8575c6c
BS
912 goto err;
913 }
421522eb
DG
914 sev->build_id = status.build;
915 sev->api_major = status.api_major;
916 sev->api_minor = status.api_minor;
d8575c6c 917
6b98e96f 918 if (sev_es_enabled()) {
9681f867
TL
919 if (!kvm_kernel_irqchip_allowed()) {
920 error_report("%s: SEV-ES guests require in-kernel irqchip support",
921 __func__);
922 goto err;
923 }
924
6b98e96f
TL
925 if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
926 error_report("%s: guest policy requires SEV-ES, but "
927 "host SEV-ES support unavailable",
928 __func__);
929 goto err;
930 }
931 cmd = KVM_SEV_ES_INIT;
932 } else {
933 cmd = KVM_SEV_INIT;
934 }
935
d8575c6c 936 trace_kvm_sev_init();
6b98e96f 937 ret = sev_ioctl(sev->sev_fd, cmd, NULL, &fw_error);
d8575c6c 938 if (ret) {
c9f5aaa6
DG
939 error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
940 __func__, ret, fw_error, fw_error_to_str(fw_error));
d8575c6c
BS
941 goto err;
942 }
943
75a877e3 944 ret = sev_launch_start(sev);
620fd55c 945 if (ret) {
c9f5aaa6 946 error_setg(errp, "%s: failed to create encryption context", __func__);
620fd55c
BS
947 goto err;
948 }
949
2b308e44 950 ram_block_notifier_add(&sev_ram_notifier);
c6c89c97 951 qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
8673dee3 952 qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
2b308e44 953
abc27d42
DG
954 cgs->ready = true;
955
aacdb844 956 return 0;
d8575c6c 957err:
8673dee3 958 sev_guest = NULL;
fee3f3ba 959 ram_block_discard_disable(false);
aacdb844 960 return -1;
d8575c6c
BS
961}
962
b738d630 963int
aacdb844 964sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
b738d630 965{
aacdb844
DG
966 if (!sev_guest) {
967 return 0;
968 }
b738d630
BS
969
970 /* if SEV is in update state then encrypt the data else do nothing */
aacdb844
DG
971 if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
972 int ret = sev_launch_update_data(sev_guest, ptr, len);
973 if (ret < 0) {
2c7233eb 974 error_setg(errp, "SEV: Failed to encrypt pflash rom");
aacdb844
DG
975 return ret;
976 }
b738d630
BS
977 }
978
979 return 0;
980}
981
c7f7e697
TFF
982int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
983 uint64_t gpa, Error **errp)
984{
985 struct kvm_sev_launch_secret input;
986 g_autofree guchar *data = NULL, *hdr = NULL;
987 int error, ret = 1;
988 void *hva;
989 gsize hdr_sz = 0, data_sz = 0;
990 MemoryRegion *mr = NULL;
991
992 if (!sev_guest) {
2c7233eb 993 error_setg(errp, "SEV not enabled for guest");
c7f7e697
TFF
994 return 1;
995 }
996
997 /* secret can be injected only in this state */
998 if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
999 error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
1000 sev_guest->state);
1001 return 1;
1002 }
1003
1004 hdr = g_base64_decode(packet_hdr, &hdr_sz);
1005 if (!hdr || !hdr_sz) {
1006 error_setg(errp, "SEV: Failed to decode sequence header");
1007 return 1;
1008 }
1009
1010 data = g_base64_decode(secret, &data_sz);
1011 if (!data || !data_sz) {
1012 error_setg(errp, "SEV: Failed to decode data");
1013 return 1;
1014 }
1015
1016 hva = gpa2hva(&mr, gpa, data_sz, errp);
1017 if (!hva) {
1018 error_prepend(errp, "SEV: Failed to calculate guest address: ");
1019 return 1;
1020 }
1021
1022 input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
1023 input.hdr_len = hdr_sz;
1024
1025 input.trans_uaddr = (uint64_t)(unsigned long)data;
1026 input.trans_len = data_sz;
1027
1028 input.guest_uaddr = (uint64_t)(unsigned long)hva;
1029 input.guest_len = data_sz;
1030
1031 trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
1032 input.trans_uaddr, input.trans_len);
1033
1034 ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
1035 &input, &error);
1036 if (ret) {
1037 error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
1038 ret, error, fw_error_to_str(error));
1039 return ret;
1040 }
1041
1042 return 0;
1043}
1044
11a6ed0e
PMD
1045#define SEV_SECRET_GUID "4c2eb361-7d9b-4cc3-8081-127c90d3d294"
1046struct sev_secret_area {
1047 uint32_t base;
1048 uint32_t size;
1049};
1050
1051void qmp_sev_inject_launch_secret(const char *packet_hdr,
1052 const char *secret,
1053 bool has_gpa, uint64_t gpa,
1054 Error **errp)
1055{
1056 if (!sev_enabled()) {
1057 error_setg(errp, "SEV not enabled for guest");
1058 return;
1059 }
1060 if (!has_gpa) {
1061 uint8_t *data;
1062 struct sev_secret_area *area;
1063
1064 if (!pc_system_ovmf_table_find(SEV_SECRET_GUID, &data, NULL)) {
1065 error_setg(errp, "SEV: no secret area found in OVMF,"
1066 " gpa must be specified.");
1067 return;
1068 }
1069 area = (struct sev_secret_area *)data;
1070 gpa = area->base;
1071 }
1072
1073 sev_inject_launch_secret(packet_hdr, secret, gpa, errp);
1074}
1075
b2f73a07
PB
1076static int
1077sev_es_parse_reset_block(SevInfoBlock *info, uint32_t *addr)
1078{
1079 if (!info->reset_addr) {
1080 error_report("SEV-ES reset address is zero");
1081 return 1;
1082 }
1083
1084 *addr = info->reset_addr;
1085
1086 return 0;
1087}
1088
1089static int
1090sev_es_find_reset_vector(void *flash_ptr, uint64_t flash_size,
1091 uint32_t *addr)
1092{
1093 QemuUUID info_guid, *guid;
1094 SevInfoBlock *info;
1095 uint8_t *data;
1096 uint16_t *len;
1097
1098 /*
1099 * Initialize the address to zero. An address of zero with a successful
1100 * return code indicates that SEV-ES is not active.
1101 */
1102 *addr = 0;
1103
1104 /*
1105 * Extract the AP reset vector for SEV-ES guests by locating the SEV GUID.
1106 * The SEV GUID is located on its own (original implementation) or within
1107 * the Firmware GUID Table (new implementation), either of which are
1108 * located 32 bytes from the end of the flash.
1109 *
1110 * Check the Firmware GUID Table first.
1111 */
1112 if (pc_system_ovmf_table_find(SEV_INFO_BLOCK_GUID, &data, NULL)) {
1113 return sev_es_parse_reset_block((SevInfoBlock *)data, addr);
1114 }
1115
1116 /*
1117 * SEV info block not found in the Firmware GUID Table (or there isn't
1118 * a Firmware GUID Table), fall back to the original implementation.
1119 */
1120 data = flash_ptr + flash_size - 0x20;
1121
1122 qemu_uuid_parse(SEV_INFO_BLOCK_GUID, &info_guid);
1123 info_guid = qemu_uuid_bswap(info_guid); /* GUIDs are LE */
1124
1125 guid = (QemuUUID *)(data - sizeof(info_guid));
1126 if (!qemu_uuid_is_equal(guid, &info_guid)) {
1127 error_report("SEV information block/Firmware GUID Table block not found in pflash rom");
1128 return 1;
1129 }
1130
1131 len = (uint16_t *)((uint8_t *)guid - sizeof(*len));
1132 info = (SevInfoBlock *)(data - le16_to_cpu(*len));
1133
1134 return sev_es_parse_reset_block(info, addr);
1135}
1136
1137void sev_es_set_reset_vector(CPUState *cpu)
1138{
1139 X86CPU *x86;
1140 CPUX86State *env;
1141
1142 /* Only update if we have valid reset information */
1143 if (!sev_guest || !sev_guest->reset_data_valid) {
1144 return;
1145 }
1146
1147 /* Do not update the BSP reset state */
1148 if (cpu->cpu_index == 0) {
1149 return;
1150 }
1151
1152 x86 = X86_CPU(cpu);
1153 env = &x86->env;
1154
1155 cpu_x86_load_seg_cache(env, R_CS, 0xf000, sev_guest->reset_cs, 0xffff,
1156 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
1157 DESC_R_MASK | DESC_A_MASK);
1158
1159 env->eip = sev_guest->reset_ip;
1160}
1161
1162int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
1163{
1164 CPUState *cpu;
1165 uint32_t addr;
1166 int ret;
1167
1168 if (!sev_es_enabled()) {
1169 return 0;
1170 }
1171
1172 addr = 0;
1173 ret = sev_es_find_reset_vector(flash_ptr, flash_size,
1174 &addr);
1175 if (ret) {
1176 return ret;
1177 }
1178
1179 if (addr) {
1180 sev_guest->reset_cs = addr & 0xffff0000;
1181 sev_guest->reset_ip = addr & 0x0000ffff;
1182 sev_guest->reset_data_valid = true;
1183
1184 CPU_FOREACH(cpu) {
1185 sev_es_set_reset_vector(cpu);
1186 }
1187 }
1188
1189 return 0;
1190}
1191
cff03145
DM
1192static const QemuUUID sev_hash_table_header_guid = {
1193 .data = UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93,
1194 0xd4, 0x11, 0xfd, 0x21)
1195};
1196
1197static const QemuUUID sev_kernel_entry_guid = {
1198 .data = UUID_LE(0x4de79437, 0xabd2, 0x427f, 0xb8, 0x35, 0xd5, 0xb1,
1199 0x72, 0xd2, 0x04, 0x5b)
1200};
1201static const QemuUUID sev_initrd_entry_guid = {
1202 .data = UUID_LE(0x44baf731, 0x3a2f, 0x4bd7, 0x9a, 0xf1, 0x41, 0xe2,
1203 0x91, 0x69, 0x78, 0x1d)
1204};
1205static const QemuUUID sev_cmdline_entry_guid = {
1206 .data = UUID_LE(0x97d02dd8, 0xbd20, 0x4c94, 0xaa, 0x78, 0xe7, 0x71,
1207 0x4d, 0x36, 0xab, 0x2a)
1208};
1209
1210/*
1211 * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
1212 * which is included in SEV's initial memory measurement.
1213 */
1214bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
1215{
1216 uint8_t *data;
1217 SevHashTableDescriptor *area;
1218 SevHashTable *ht;
1219 uint8_t cmdline_hash[HASH_SIZE];
1220 uint8_t initrd_hash[HASH_SIZE];
1221 uint8_t kernel_hash[HASH_SIZE];
1222 uint8_t *hashp;
1223 size_t hash_len = HASH_SIZE;
1224 int aligned_len;
1225
9dbe0c93
DM
1226 /*
1227 * Only add the kernel hashes if the sev-guest configuration explicitly
1228 * stated kernel-hashes=on.
1229 */
1230 if (!sev_guest->kernel_hashes) {
1231 return false;
1232 }
1233
cff03145 1234 if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
5a0294a2
DM
1235 error_setg(errp, "SEV: kernel specified but guest firmware "
1236 "has no hashes table GUID");
cff03145
DM
1237 return false;
1238 }
1239 area = (SevHashTableDescriptor *)data;
1240
1241 /*
1242 * Calculate hash of kernel command-line with the terminating null byte. If
1243 * the user doesn't supply a command-line via -append, the 1-byte "\0" will
1244 * be used.
1245 */
1246 hashp = cmdline_hash;
1247 if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->cmdline_data,
1248 ctx->cmdline_size, &hashp, &hash_len, errp) < 0) {
1249 return false;
1250 }
1251 assert(hash_len == HASH_SIZE);
1252
1253 /*
1254 * Calculate hash of initrd. If the user doesn't supply an initrd via
1255 * -initrd, an empty buffer will be used (ctx->initrd_size == 0).
1256 */
1257 hashp = initrd_hash;
1258 if (qcrypto_hash_bytes(QCRYPTO_HASH_ALG_SHA256, ctx->initrd_data,
1259 ctx->initrd_size, &hashp, &hash_len, errp) < 0) {
1260 return false;
1261 }
1262 assert(hash_len == HASH_SIZE);
1263
1264 /* Calculate hash of the kernel */
1265 hashp = kernel_hash;
1266 struct iovec iov[2] = {
1267 { .iov_base = ctx->setup_data, .iov_len = ctx->setup_size },
1268 { .iov_base = ctx->kernel_data, .iov_len = ctx->kernel_size }
1269 };
1270 if (qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256, iov, ARRAY_SIZE(iov),
1271 &hashp, &hash_len, errp) < 0) {
1272 return false;
1273 }
1274 assert(hash_len == HASH_SIZE);
1275
1276 /*
1277 * Populate the hashes table in the guest's memory at the OVMF-designated
1278 * area for the SEV hashes table
1279 */
1280 ht = qemu_map_ram_ptr(NULL, area->base);
1281
1282 ht->guid = sev_hash_table_header_guid;
1283 ht->len = sizeof(*ht);
1284
1285 ht->cmdline.guid = sev_cmdline_entry_guid;
1286 ht->cmdline.len = sizeof(ht->cmdline);
1287 memcpy(ht->cmdline.hash, cmdline_hash, sizeof(ht->cmdline.hash));
1288
1289 ht->initrd.guid = sev_initrd_entry_guid;
1290 ht->initrd.len = sizeof(ht->initrd);
1291 memcpy(ht->initrd.hash, initrd_hash, sizeof(ht->initrd.hash));
1292
1293 ht->kernel.guid = sev_kernel_entry_guid;
1294 ht->kernel.len = sizeof(ht->kernel);
1295 memcpy(ht->kernel.hash, kernel_hash, sizeof(ht->kernel.hash));
1296
1297 /* When calling sev_encrypt_flash, the length has to be 16 byte aligned */
1298 aligned_len = ROUND_UP(ht->len, 16);
1299 if (aligned_len != ht->len) {
1300 /* zero the excess data so the measurement can be reliably calculated */
1301 memset(ht->padding, 0, aligned_len - ht->len);
1302 }
1303
1304 if (sev_encrypt_flash((uint8_t *)ht, aligned_len, errp) < 0) {
1305 return false;
1306 }
1307
1308 return true;
1309}
1310
a9b4942f
BS
1311static void
1312sev_register_types(void)
1313{
d2d8a198 1314 type_register_static(&sev_guest_info);
a9b4942f
BS
1315}
1316
1317type_init(sev_register_types);
This page took 0.404599 seconds and 4 git commands to generate.