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