diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index 60b3d5bceb..988201e3f9 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -48,6 +48,10 @@ module Libvirtd_qemu =
| bool_entry "spice_sasl"
| str_entry "spice_sasl_dir"
+ let chardev_entry = bool_entry "chardev_tls"
+ | str_entry "chardev_tls_x509_cert_dir"
+ | bool_entry "chardev_tls_x509_verify"
+
let nogfx_entry = bool_entry "nographics_allow_host_audio"
let remote_display_entry = int_entry "remote_display_port_min"
@@ -104,6 +108,7 @@ module Libvirtd_qemu =
let entry = default_tls_entry
| vnc_entry
| spice_entry
+ | chardev_entry
| nogfx_entry
| remote_display_entry
| security_entry
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 1385433c60..e4c2aae2ec 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -185,6 +185,34 @@
#
#spice_sasl_dir = "/some/directory/sasl2"
+# Enable use of TLS encryption on the chardev TCP transports.
+#
+# It is necessary to setup CA and issue a server certificate
+# before enabling this.
+#
+#chardev_tls = 1
+
+
+# In order to override the default TLS certificate location for character
+# device TCP certificates, supply a valid path to the certificate directory.
+# If the provided path does not exist then the default_tls_x509_cert_dir
+# path will be used.
+#
+#chardev_tls_x509_cert_dir = "/etc/pki/libvirt-chardev"
+
+
+# The default TLS configuration only uses certificates for the server
+# allowing the client to verify the server's identity and establish
+# an encrypted channel.
+#
+# It is possible to use x509 certificates for authentication too, by
+# issuing a x509 certificate to every client who needs to connect.
+#
+# Enabling this option will reject any client who does not have a
+# certificate signed by the CA in /etc/pki/libvirt-chardev/ca-cert.pem
+#
+#chardev_tls_x509_verify = 1
+
# By default, if no graphical front end is configured, libvirt will disable
# QEMU audio output since directly talking to alsa/pulseaudio may not work
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index fba351432e..e7b2d8d3ad 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -274,6 +274,7 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
SET_TLS_X509_CERT_DEFAULT(vnc);
SET_TLS_X509_CERT_DEFAULT(spice);
+ SET_TLS_X509_CERT_DEFAULT(chardev);
#undef SET_TLS_X509_CERT_DEFAULT
@@ -375,6 +376,8 @@ static void virQEMUDriverConfigDispose(void *obj)
VIR_FREE(cfg->spicePassword);
VIR_FREE(cfg->spiceSASLdir);
+ VIR_FREE(cfg->chardevTLSx509certdir);
+
while (cfg->nhugetlbfs) {
cfg->nhugetlbfs--;
VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
@@ -502,6 +505,14 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
if (virConfGetValueBool(conf, "spice_auto_unix_socket", &cfg->spiceAutoUnixSocket) < 0)
goto cleanup;
+ if (virConfGetValueBool(conf, "chardev_tls", &cfg->chardevTLS) < 0)
+ goto cleanup;
+ if (virConfGetValueString(conf, "chardev_tls_x509_cert_dir", &cfg->chardevTLSx509certdir) < 0)
+ goto cleanup;
+ if ((rv = virConfGetValueBool(conf, "chardev_tls_x509_verify", &cfg->chardevTLSx509verify)) < 0)
+ goto cleanup;
+ if (rv == 0)
+ cfg->chardevTLSx509verify = cfg->defaultTLSx509verify;
if (virConfGetValueUInt(conf, "remote_websocket_port_min", &cfg->webSocketPortMin) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index c1ba24c3f5..d8232cc7e6 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -129,6 +129,10 @@ struct _virQEMUDriverConfig {
char *spicePassword;
bool spiceAutoUnixSocket;
+ bool chardevTLS;
+ char *chardevTLSx509certdir;
+ bool chardevTLSx509verify;
+
unsigned int remotePortMin;
unsigned int remotePortMax;
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index 176db33f58..cd162ae1a6 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -20,6 +20,9 @@ module Test_libvirtd_qemu =
{ "spice_password" = "XYZ12345" }
{ "spice_sasl" = "1" }
{ "spice_sasl_dir" = "/some/directory/sasl2" }
+{ "chardev_tls" = "1" }
+{ "chardev_tls_x509_cert_dir" = "/etc/pki/libvirt-chardev" }
+{ "chardev_tls_x509_verify" = "1" }
{ "nographics_allow_host_audio" = "1" }
{ "remote_display_port_min" = "5900" }
{ "remote_display_port_max" = "65535" }
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml
new file mode 100644
index 0000000000..1618b029d9
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-tcp-tlsx509-chardev.xml
@@ -0,0 +1,41 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
new file mode 100644
index 0000000000..832e2a2c8b
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-serial-tcp-tlsx509-chardev.xml
@@ -0,0 +1,50 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 7601a5f2d2..8cdd2d7152 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -532,6 +532,7 @@ mymain(void)
DO_TEST("serial-tcp", NONE);
DO_TEST("serial-udp", NONE);
DO_TEST("serial-tcp-telnet", NONE);
+ DO_TEST("serial-tcp-tlsx509-chardev", NONE);
DO_TEST("serial-many", NONE);
DO_TEST("serial-spiceport", NONE);
DO_TEST("serial-spiceport-nospice", NONE);