xref: /qemu/target/i386/sev.c (revision ec63e06e)
1 /*
2  * QEMU SEV support
3  *
4  * Copyright Advanced Micro Devices 2016-2018
5  *
6  * Author:
7  *      Brijesh Singh <brijesh.singh@amd.com>
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 
14 #include "qemu/osdep.h"
15 
16 #include <linux/kvm.h>
17 #include <linux/psp-sev.h>
18 
19 #include <sys/ioctl.h>
20 
21 #include "qapi/error.h"
22 #include "qom/object_interfaces.h"
23 #include "qemu/base64.h"
24 #include "qemu/module.h"
25 #include "sysemu/kvm.h"
26 #include "sev_i386.h"
27 #include "sysemu/sysemu.h"
28 #include "sysemu/runstate.h"
29 #include "trace.h"
30 #include "migration/blocker.h"
31 #include "qom/object.h"
32 #include "exec/address-spaces.h"
33 #include "monitor/monitor.h"
34 #include "exec/confidential-guest-support.h"
35 
36 #define TYPE_SEV_GUEST "sev-guest"
37 OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
38 
39 
40 /**
41  * SevGuestState:
42  *
43  * The SevGuestState object is used for creating and managing a SEV
44  * guest.
45  *
46  * # $QEMU \
47  *         -object sev-guest,id=sev0 \
48  *         -machine ...,memory-encryption=sev0
49  */
50 struct SevGuestState {
51     ConfidentialGuestSupport parent_obj;
52 
53     /* configuration parameters */
54     char *sev_device;
55     uint32_t policy;
56     char *dh_cert_file;
57     char *session_file;
58     uint32_t cbitpos;
59     uint32_t reduced_phys_bits;
60 
61     /* runtime state */
62     uint32_t handle;
63     uint8_t api_major;
64     uint8_t api_minor;
65     uint8_t build_id;
66     uint64_t me_mask;
67     int sev_fd;
68     SevState state;
69     gchar *measurement;
70 };
71 
72 #define DEFAULT_GUEST_POLICY    0x1 /* disable debug */
73 #define DEFAULT_SEV_DEVICE      "/dev/sev"
74 
75 static SevGuestState *sev_guest;
76 static Error *sev_mig_blocker;
77 
78 static const char *const sev_fw_errlist[] = {
79     "",
80     "Platform state is invalid",
81     "Guest state is invalid",
82     "Platform configuration is invalid",
83     "Buffer too small",
84     "Platform is already owned",
85     "Certificate is invalid",
86     "Policy is not allowed",
87     "Guest is not active",
88     "Invalid address",
89     "Bad signature",
90     "Bad measurement",
91     "Asid is already owned",
92     "Invalid ASID",
93     "WBINVD is required",
94     "DF_FLUSH is required",
95     "Guest handle is invalid",
96     "Invalid command",
97     "Guest is active",
98     "Hardware error",
99     "Hardware unsafe",
100     "Feature not supported",
101     "Invalid parameter"
102 };
103 
104 #define SEV_FW_MAX_ERROR      ARRAY_SIZE(sev_fw_errlist)
105 
106 static int
107 sev_ioctl(int fd, int cmd, void *data, int *error)
108 {
109     int r;
110     struct kvm_sev_cmd input;
111 
112     memset(&input, 0x0, sizeof(input));
113 
114     input.id = cmd;
115     input.sev_fd = fd;
116     input.data = (__u64)(unsigned long)data;
117 
118     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, &input);
119 
120     if (error) {
121         *error = input.error;
122     }
123 
124     return r;
125 }
126 
127 static int
128 sev_platform_ioctl(int fd, int cmd, void *data, int *error)
129 {
130     int r;
131     struct sev_issue_cmd arg;
132 
133     arg.cmd = cmd;
134     arg.data = (unsigned long)data;
135     r = ioctl(fd, SEV_ISSUE_CMD, &arg);
136     if (error) {
137         *error = arg.error;
138     }
139 
140     return r;
141 }
142 
143 static const char *
144 fw_error_to_str(int code)
145 {
146     if (code < 0 || code >= SEV_FW_MAX_ERROR) {
147         return "unknown error";
148     }
149 
150     return sev_fw_errlist[code];
151 }
152 
153 static bool
154 sev_check_state(const SevGuestState *sev, SevState state)
155 {
156     assert(sev);
157     return sev->state == state ? true : false;
158 }
159 
160 static void
161 sev_set_guest_state(SevGuestState *sev, SevState new_state)
162 {
163     assert(new_state < SEV_STATE__MAX);
164     assert(sev);
165 
166     trace_kvm_sev_change_state(SevState_str(sev->state),
167                                SevState_str(new_state));
168     sev->state = new_state;
169 }
170 
171 static void
172 sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
173 {
174     int r;
175     struct kvm_enc_region range;
176     ram_addr_t offset;
177     MemoryRegion *mr;
178 
179     /*
180      * The RAM device presents a memory region that should be treated
181      * as IO region and should not be pinned.
182      */
183     mr = memory_region_from_host(host, &offset);
184     if (mr && memory_region_is_ram_device(mr)) {
185         return;
186     }
187 
188     range.addr = (__u64)(unsigned long)host;
189     range.size = size;
190 
191     trace_kvm_memcrypt_register_region(host, size);
192     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
193     if (r) {
194         error_report("%s: failed to register region (%p+%#zx) error '%s'",
195                      __func__, host, size, strerror(errno));
196         exit(1);
197     }
198 }
199 
200 static void
201 sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size)
202 {
203     int r;
204     struct kvm_enc_region range;
205     ram_addr_t offset;
206     MemoryRegion *mr;
207 
208     /*
209      * The RAM device presents a memory region that should be treated
210      * as IO region and should not have been pinned.
211      */
212     mr = memory_region_from_host(host, &offset);
213     if (mr && memory_region_is_ram_device(mr)) {
214         return;
215     }
216 
217     range.addr = (__u64)(unsigned long)host;
218     range.size = size;
219 
220     trace_kvm_memcrypt_unregister_region(host, size);
221     r = kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_UNREG_REGION, &range);
222     if (r) {
223         error_report("%s: failed to unregister region (%p+%#zx)",
224                      __func__, host, size);
225     }
226 }
227 
228 static struct RAMBlockNotifier sev_ram_notifier = {
229     .ram_block_added = sev_ram_block_added,
230     .ram_block_removed = sev_ram_block_removed,
231 };
232 
233 static void
234 sev_guest_finalize(Object *obj)
235 {
236 }
237 
238 static char *
239 sev_guest_get_session_file(Object *obj, Error **errp)
240 {
241     SevGuestState *s = SEV_GUEST(obj);
242 
243     return s->session_file ? g_strdup(s->session_file) : NULL;
244 }
245 
246 static void
247 sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
248 {
249     SevGuestState *s = SEV_GUEST(obj);
250 
251     s->session_file = g_strdup(value);
252 }
253 
254 static char *
255 sev_guest_get_dh_cert_file(Object *obj, Error **errp)
256 {
257     SevGuestState *s = SEV_GUEST(obj);
258 
259     return g_strdup(s->dh_cert_file);
260 }
261 
262 static void
263 sev_guest_set_dh_cert_file(Object *obj, const char *value, Error **errp)
264 {
265     SevGuestState *s = SEV_GUEST(obj);
266 
267     s->dh_cert_file = g_strdup(value);
268 }
269 
270 static char *
271 sev_guest_get_sev_device(Object *obj, Error **errp)
272 {
273     SevGuestState *sev = SEV_GUEST(obj);
274 
275     return g_strdup(sev->sev_device);
276 }
277 
278 static void
279 sev_guest_set_sev_device(Object *obj, const char *value, Error **errp)
280 {
281     SevGuestState *sev = SEV_GUEST(obj);
282 
283     sev->sev_device = g_strdup(value);
284 }
285 
286 static void
287 sev_guest_class_init(ObjectClass *oc, void *data)
288 {
289     object_class_property_add_str(oc, "sev-device",
290                                   sev_guest_get_sev_device,
291                                   sev_guest_set_sev_device);
292     object_class_property_set_description(oc, "sev-device",
293             "SEV device to use");
294     object_class_property_add_str(oc, "dh-cert-file",
295                                   sev_guest_get_dh_cert_file,
296                                   sev_guest_set_dh_cert_file);
297     object_class_property_set_description(oc, "dh-cert-file",
298             "guest owners DH certificate (encoded with base64)");
299     object_class_property_add_str(oc, "session-file",
300                                   sev_guest_get_session_file,
301                                   sev_guest_set_session_file);
302     object_class_property_set_description(oc, "session-file",
303             "guest owners session parameters (encoded with base64)");
304 }
305 
306 static void
307 sev_guest_instance_init(Object *obj)
308 {
309     SevGuestState *sev = SEV_GUEST(obj);
310 
311     sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
312     sev->policy = DEFAULT_GUEST_POLICY;
313     object_property_add_uint32_ptr(obj, "policy", &sev->policy,
314                                    OBJ_PROP_FLAG_READWRITE);
315     object_property_add_uint32_ptr(obj, "handle", &sev->handle,
316                                    OBJ_PROP_FLAG_READWRITE);
317     object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
318                                    OBJ_PROP_FLAG_READWRITE);
319     object_property_add_uint32_ptr(obj, "reduced-phys-bits",
320                                    &sev->reduced_phys_bits,
321                                    OBJ_PROP_FLAG_READWRITE);
322 }
323 
324 /* sev guest info */
325 static const TypeInfo sev_guest_info = {
326     .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
327     .name = TYPE_SEV_GUEST,
328     .instance_size = sizeof(SevGuestState),
329     .instance_finalize = sev_guest_finalize,
330     .class_init = sev_guest_class_init,
331     .instance_init = sev_guest_instance_init,
332     .interfaces = (InterfaceInfo[]) {
333         { TYPE_USER_CREATABLE },
334         { }
335     }
336 };
337 
338 bool
339 sev_enabled(void)
340 {
341     return !!sev_guest;
342 }
343 
344 uint64_t
345 sev_get_me_mask(void)
346 {
347     return sev_guest ? sev_guest->me_mask : ~0;
348 }
349 
350 uint32_t
351 sev_get_cbit_position(void)
352 {
353     return sev_guest ? sev_guest->cbitpos : 0;
354 }
355 
356 uint32_t
357 sev_get_reduced_phys_bits(void)
358 {
359     return sev_guest ? sev_guest->reduced_phys_bits : 0;
360 }
361 
362 SevInfo *
363 sev_get_info(void)
364 {
365     SevInfo *info;
366 
367     info = g_new0(SevInfo, 1);
368     info->enabled = sev_enabled();
369 
370     if (info->enabled) {
371         info->api_major = sev_guest->api_major;
372         info->api_minor = sev_guest->api_minor;
373         info->build_id = sev_guest->build_id;
374         info->policy = sev_guest->policy;
375         info->state = sev_guest->state;
376         info->handle = sev_guest->handle;
377     }
378 
379     return info;
380 }
381 
382 static int
383 sev_get_pdh_info(int fd, guchar **pdh, size_t *pdh_len, guchar **cert_chain,
384                  size_t *cert_chain_len, Error **errp)
385 {
386     guchar *pdh_data = NULL;
387     guchar *cert_chain_data = NULL;
388     struct sev_user_data_pdh_cert_export export = {};
389     int err, r;
390 
391     /* query the certificate length */
392     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
393     if (r < 0) {
394         if (err != SEV_RET_INVALID_LEN) {
395             error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
396                        r, err, fw_error_to_str(err));
397             return 1;
398         }
399     }
400 
401     pdh_data = g_new(guchar, export.pdh_cert_len);
402     cert_chain_data = g_new(guchar, export.cert_chain_len);
403     export.pdh_cert_address = (unsigned long)pdh_data;
404     export.cert_chain_address = (unsigned long)cert_chain_data;
405 
406     r = sev_platform_ioctl(fd, SEV_PDH_CERT_EXPORT, &export, &err);
407     if (r < 0) {
408         error_setg(errp, "failed to export PDH cert ret=%d fw_err=%d (%s)",
409                    r, err, fw_error_to_str(err));
410         goto e_free;
411     }
412 
413     *pdh = pdh_data;
414     *pdh_len = export.pdh_cert_len;
415     *cert_chain = cert_chain_data;
416     *cert_chain_len = export.cert_chain_len;
417     return 0;
418 
419 e_free:
420     g_free(pdh_data);
421     g_free(cert_chain_data);
422     return 1;
423 }
424 
425 SevCapability *
426 sev_get_capabilities(Error **errp)
427 {
428     SevCapability *cap = NULL;
429     guchar *pdh_data = NULL;
430     guchar *cert_chain_data = NULL;
431     size_t pdh_len = 0, cert_chain_len = 0;
432     uint32_t ebx;
433     int fd;
434 
435     if (!kvm_enabled()) {
436         error_setg(errp, "KVM not enabled");
437         return NULL;
438     }
439     if (kvm_vm_ioctl(kvm_state, KVM_MEMORY_ENCRYPT_OP, NULL) < 0) {
440         error_setg(errp, "SEV is not enabled in KVM");
441         return NULL;
442     }
443 
444     fd = open(DEFAULT_SEV_DEVICE, O_RDWR);
445     if (fd < 0) {
446         error_setg_errno(errp, errno, "Failed to open %s",
447                          DEFAULT_SEV_DEVICE);
448         return NULL;
449     }
450 
451     if (sev_get_pdh_info(fd, &pdh_data, &pdh_len,
452                          &cert_chain_data, &cert_chain_len, errp)) {
453         goto out;
454     }
455 
456     cap = g_new0(SevCapability, 1);
457     cap->pdh = g_base64_encode(pdh_data, pdh_len);
458     cap->cert_chain = g_base64_encode(cert_chain_data, cert_chain_len);
459 
460     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
461     cap->cbitpos = ebx & 0x3f;
462 
463     /*
464      * When SEV feature is enabled, we loose one bit in guest physical
465      * addressing.
466      */
467     cap->reduced_phys_bits = 1;
468 
469 out:
470     g_free(pdh_data);
471     g_free(cert_chain_data);
472     close(fd);
473     return cap;
474 }
475 
476 static int
477 sev_read_file_base64(const char *filename, guchar **data, gsize *len)
478 {
479     gsize sz;
480     gchar *base64;
481     GError *error = NULL;
482 
483     if (!g_file_get_contents(filename, &base64, &sz, &error)) {
484         error_report("failed to read '%s' (%s)", filename, error->message);
485         g_error_free(error);
486         return -1;
487     }
488 
489     *data = g_base64_decode(base64, len);
490     return 0;
491 }
492 
493 static int
494 sev_launch_start(SevGuestState *sev)
495 {
496     gsize sz;
497     int ret = 1;
498     int fw_error, rc;
499     struct kvm_sev_launch_start *start;
500     guchar *session = NULL, *dh_cert = NULL;
501 
502     start = g_new0(struct kvm_sev_launch_start, 1);
503 
504     start->handle = sev->handle;
505     start->policy = sev->policy;
506     if (sev->session_file) {
507         if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
508             goto out;
509         }
510         start->session_uaddr = (unsigned long)session;
511         start->session_len = sz;
512     }
513 
514     if (sev->dh_cert_file) {
515         if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
516             goto out;
517         }
518         start->dh_uaddr = (unsigned long)dh_cert;
519         start->dh_len = sz;
520     }
521 
522     trace_kvm_sev_launch_start(start->policy, session, dh_cert);
523     rc = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
524     if (rc < 0) {
525         error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
526                 __func__, ret, fw_error, fw_error_to_str(fw_error));
527         goto out;
528     }
529 
530     sev_set_guest_state(sev, SEV_STATE_LAUNCH_UPDATE);
531     sev->handle = start->handle;
532     ret = 0;
533 
534 out:
535     g_free(start);
536     g_free(session);
537     g_free(dh_cert);
538     return ret;
539 }
540 
541 static int
542 sev_launch_update_data(SevGuestState *sev, uint8_t *addr, uint64_t len)
543 {
544     int ret, fw_error;
545     struct kvm_sev_launch_update_data update;
546 
547     if (!addr || !len) {
548         return 1;
549     }
550 
551     update.uaddr = (__u64)(unsigned long)addr;
552     update.len = len;
553     trace_kvm_sev_launch_update_data(addr, len);
554     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
555                     &update, &fw_error);
556     if (ret) {
557         error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
558                 __func__, ret, fw_error, fw_error_to_str(fw_error));
559     }
560 
561     return ret;
562 }
563 
564 static void
565 sev_launch_get_measure(Notifier *notifier, void *unused)
566 {
567     SevGuestState *sev = sev_guest;
568     int ret, error;
569     guchar *data;
570     struct kvm_sev_launch_measure *measurement;
571 
572     if (!sev_check_state(sev, SEV_STATE_LAUNCH_UPDATE)) {
573         return;
574     }
575 
576     measurement = g_new0(struct kvm_sev_launch_measure, 1);
577 
578     /* query the measurement blob length */
579     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
580                     measurement, &error);
581     if (!measurement->len) {
582         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
583                      __func__, ret, error, fw_error_to_str(errno));
584         goto free_measurement;
585     }
586 
587     data = g_new0(guchar, measurement->len);
588     measurement->uaddr = (unsigned long)data;
589 
590     /* get the measurement blob */
591     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_MEASURE,
592                     measurement, &error);
593     if (ret) {
594         error_report("%s: LAUNCH_MEASURE ret=%d fw_error=%d '%s'",
595                      __func__, ret, error, fw_error_to_str(errno));
596         goto free_data;
597     }
598 
599     sev_set_guest_state(sev, SEV_STATE_LAUNCH_SECRET);
600 
601     /* encode the measurement value and emit the event */
602     sev->measurement = g_base64_encode(data, measurement->len);
603     trace_kvm_sev_launch_measurement(sev->measurement);
604 
605 free_data:
606     g_free(data);
607 free_measurement:
608     g_free(measurement);
609 }
610 
611 char *
612 sev_get_launch_measurement(void)
613 {
614     if (sev_guest &&
615         sev_guest->state >= SEV_STATE_LAUNCH_SECRET) {
616         return g_strdup(sev_guest->measurement);
617     }
618 
619     return NULL;
620 }
621 
622 static Notifier sev_machine_done_notify = {
623     .notify = sev_launch_get_measure,
624 };
625 
626 static void
627 sev_launch_finish(SevGuestState *sev)
628 {
629     int ret, error;
630     Error *local_err = NULL;
631 
632     trace_kvm_sev_launch_finish();
633     ret = sev_ioctl(sev->sev_fd, KVM_SEV_LAUNCH_FINISH, 0, &error);
634     if (ret) {
635         error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
636                      __func__, ret, error, fw_error_to_str(error));
637         exit(1);
638     }
639 
640     sev_set_guest_state(sev, SEV_STATE_RUNNING);
641 
642     /* add migration blocker */
643     error_setg(&sev_mig_blocker,
644                "SEV: Migration is not implemented");
645     ret = migrate_add_blocker(sev_mig_blocker, &local_err);
646     if (local_err) {
647         error_report_err(local_err);
648         error_free(sev_mig_blocker);
649         exit(1);
650     }
651 }
652 
653 static void
654 sev_vm_state_change(void *opaque, int running, RunState state)
655 {
656     SevGuestState *sev = opaque;
657 
658     if (running) {
659         if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
660             sev_launch_finish(sev);
661         }
662     }
663 }
664 
665 int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
666 {
667     SevGuestState *sev
668         = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
669     char *devname;
670     int ret, fw_error;
671     uint32_t ebx;
672     uint32_t host_cbitpos;
673     struct sev_user_data_status status = {};
674 
675     if (!sev) {
676         return 0;
677     }
678 
679     ret = ram_block_discard_disable(true);
680     if (ret) {
681         error_report("%s: cannot disable RAM discard", __func__);
682         return -1;
683     }
684 
685     sev_guest = sev;
686     sev->state = SEV_STATE_UNINIT;
687 
688     host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
689     host_cbitpos = ebx & 0x3f;
690 
691     if (host_cbitpos != sev->cbitpos) {
692         error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
693                    __func__, host_cbitpos, sev->cbitpos);
694         goto err;
695     }
696 
697     if (sev->reduced_phys_bits < 1) {
698         error_setg(errp, "%s: reduced_phys_bits check failed, it should be >=1,"
699                    " requested '%d'", __func__, sev->reduced_phys_bits);
700         goto err;
701     }
702 
703     sev->me_mask = ~(1UL << sev->cbitpos);
704 
705     devname = object_property_get_str(OBJECT(sev), "sev-device", NULL);
706     sev->sev_fd = open(devname, O_RDWR);
707     if (sev->sev_fd < 0) {
708         error_setg(errp, "%s: Failed to open %s '%s'", __func__,
709                    devname, strerror(errno));
710         g_free(devname);
711         goto err;
712     }
713     g_free(devname);
714 
715     ret = sev_platform_ioctl(sev->sev_fd, SEV_PLATFORM_STATUS, &status,
716                              &fw_error);
717     if (ret) {
718         error_setg(errp, "%s: failed to get platform status ret=%d "
719                    "fw_error='%d: %s'", __func__, ret, fw_error,
720                    fw_error_to_str(fw_error));
721         goto err;
722     }
723     sev->build_id = status.build;
724     sev->api_major = status.api_major;
725     sev->api_minor = status.api_minor;
726 
727     trace_kvm_sev_init();
728     ret = sev_ioctl(sev->sev_fd, KVM_SEV_INIT, NULL, &fw_error);
729     if (ret) {
730         error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
731                    __func__, ret, fw_error, fw_error_to_str(fw_error));
732         goto err;
733     }
734 
735     ret = sev_launch_start(sev);
736     if (ret) {
737         error_setg(errp, "%s: failed to create encryption context", __func__);
738         goto err;
739     }
740 
741     ram_block_notifier_add(&sev_ram_notifier);
742     qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
743     qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
744 
745     cgs->ready = true;
746 
747     return 0;
748 err:
749     sev_guest = NULL;
750     ram_block_discard_disable(false);
751     return -1;
752 }
753 
754 int
755 sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
756 {
757     if (!sev_guest) {
758         return 0;
759     }
760 
761     /* if SEV is in update state then encrypt the data else do nothing */
762     if (sev_check_state(sev_guest, SEV_STATE_LAUNCH_UPDATE)) {
763         int ret = sev_launch_update_data(sev_guest, ptr, len);
764         if (ret < 0) {
765             error_setg(errp, "failed to encrypt pflash rom");
766             return ret;
767         }
768     }
769 
770     return 0;
771 }
772 
773 int sev_inject_launch_secret(const char *packet_hdr, const char *secret,
774                              uint64_t gpa, Error **errp)
775 {
776     struct kvm_sev_launch_secret input;
777     g_autofree guchar *data = NULL, *hdr = NULL;
778     int error, ret = 1;
779     void *hva;
780     gsize hdr_sz = 0, data_sz = 0;
781     MemoryRegion *mr = NULL;
782 
783     if (!sev_guest) {
784         error_setg(errp, "SEV: SEV not enabled.");
785         return 1;
786     }
787 
788     /* secret can be injected only in this state */
789     if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
790         error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
791                      sev_guest->state);
792         return 1;
793     }
794 
795     hdr = g_base64_decode(packet_hdr, &hdr_sz);
796     if (!hdr || !hdr_sz) {
797         error_setg(errp, "SEV: Failed to decode sequence header");
798         return 1;
799     }
800 
801     data = g_base64_decode(secret, &data_sz);
802     if (!data || !data_sz) {
803         error_setg(errp, "SEV: Failed to decode data");
804         return 1;
805     }
806 
807     hva = gpa2hva(&mr, gpa, data_sz, errp);
808     if (!hva) {
809         error_prepend(errp, "SEV: Failed to calculate guest address: ");
810         return 1;
811     }
812 
813     input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
814     input.hdr_len = hdr_sz;
815 
816     input.trans_uaddr = (uint64_t)(unsigned long)data;
817     input.trans_len = data_sz;
818 
819     input.guest_uaddr = (uint64_t)(unsigned long)hva;
820     input.guest_len = data_sz;
821 
822     trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
823                                 input.trans_uaddr, input.trans_len);
824 
825     ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
826                     &input, &error);
827     if (ret) {
828         error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
829                      ret, error, fw_error_to_str(error));
830         return ret;
831     }
832 
833     return 0;
834 }
835 
836 static void
837 sev_register_types(void)
838 {
839     type_register_static(&sev_guest_info);
840 }
841 
842 type_init(sev_register_types);
843