| 1 | .. _network_005ftls: |
| 2 | |
| 3 | TLS setup for network services |
| 4 | ------------------------------ |
| 5 | |
| 6 | Almost all network services in QEMU have the ability to use TLS for |
| 7 | session data encryption, along with x509 certificates for simple client |
| 8 | authentication. What follows is a description of how to generate |
| 9 | certificates suitable for usage with QEMU, and applies to the VNC |
| 10 | server, character devices with the TCP backend, NBD server and client, |
| 11 | and migration server and client. |
| 12 | |
| 13 | At a high level, QEMU requires certificates and private keys to be |
| 14 | provided in PEM format. Aside from the core fields, the certificates |
| 15 | should include various extension data sets, including v3 basic |
| 16 | constraints data, key purpose, key usage and subject alt name. |
| 17 | |
| 18 | The GnuTLS package includes a command called ``certtool`` which can be |
| 19 | used to easily generate certificates and keys in the required format |
| 20 | with expected data present. Alternatively a certificate management |
| 21 | service may be used. |
| 22 | |
| 23 | At a minimum it is necessary to setup a certificate authority, and issue |
| 24 | certificates to each server. If using x509 certificates for |
| 25 | authentication, then each client will also need to be issued a |
| 26 | certificate. |
| 27 | |
| 28 | Assuming that the QEMU network services will only ever be exposed to |
| 29 | clients on a private intranet, there is no need to use a commercial |
| 30 | certificate authority to create certificates. A self-signed CA is |
| 31 | sufficient, and in fact likely to be more secure since it removes the |
| 32 | ability of malicious 3rd parties to trick the CA into mis-issuing certs |
| 33 | for impersonating your services. The only likely exception where a |
| 34 | commercial CA might be desirable is if enabling the VNC websockets |
| 35 | server and exposing it directly to remote browser clients. In such a |
| 36 | case it might be useful to use a commercial CA to avoid needing to |
| 37 | install custom CA certs in the web browsers. |
| 38 | |
| 39 | .. _tls_cert_file_naming: |
| 40 | |
| 41 | Certificate file naming |
| 42 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 43 | |
| 44 | In a simple setup, where all QEMU instances on a machine share the |
| 45 | same TLS configuration, it is suggested that QEMU certificates be |
| 46 | kept in either ``/etc/pki/qemu`` or, for unprivileged users, in |
| 47 | ``$HOME/.pki/qemu``. Where different QEMU subsystems require |
| 48 | different certificate configurations, sub-dirs of these locations |
| 49 | may be chosen. |
| 50 | |
| 51 | The default file names that QEMU will traditionally load are: |
| 52 | |
| 53 | * ``ca-cert.pem`` - mandatory; for both client and server configurations |
| 54 | * ``ca-crl.pem`` - optional; for server configurations only |
| 55 | * ``server-cert.pem`` - mandatory; for server configurations only |
| 56 | * ``server-key.pem`` - mandatory; for server configurations only |
| 57 | * ``client-cert.pem`` - optional; for client configurations only |
| 58 | * ``client-key.pem`` - optional; for client configurations only |
| 59 | * ``dh-params.pem`` - optional; for server configurations only |
| 60 | |
| 61 | Since QEMU 10.2.0, there is support for loading upto four additional |
| 62 | identities: |
| 63 | |
| 64 | * ``server-cert-[IDX].pem`` - optional; for server configurations only |
| 65 | * ``server-key-[IDX].pem`` - optional; for server configurations only |
| 66 | * ``client-cert-[IDX].pem`` - optional; for client configurations only |
| 67 | * ``client-key-[IDX].pem`` - optional; for client configurations only |
| 68 | |
| 69 | where ``-[IDX]`` is one of the digits 0-3. Loading will terminate at |
| 70 | the first absent index. The index based certificate files may be used |
| 71 | as a replacement for, or in addition to, the traditional non-index |
| 72 | based certificate files. The traditional certificate files will be |
| 73 | loaded first, if present, then the index based certificates. Where |
| 74 | multiple certificates are compatible with a TLS session, the first |
| 75 | loaded certificate will preferred. IOW file naming can influence |
| 76 | which certificates are used for a session. |
| 77 | |
| 78 | The use of multiple sets of certificates is intended to allow an |
| 79 | incremental transition to certificates using different cryptographic |
| 80 | algorithms. This allows a newly deployed QEMU to introduce use of |
| 81 | stronger cryptographic algorithms that will be preferred when talking |
| 82 | to other newly deployed QEMU instances, while retaining compatibility |
| 83 | with certificates issued to a historically deployed QEMU. This is |
| 84 | notably useful to support live migration from an old QEMU deployed |
| 85 | on older operating system releases, which may support fewer crypto |
| 86 | algorithm choices than the current OS. |
| 87 | |
| 88 | The certificate creation commands below will be illustrated using |
| 89 | the traditional naming scheme, but their args can be substituted |
| 90 | to use the indexed naming in the obvious manner. |
| 91 | |
| 92 | .. _tls_005fgenerate_005fca: |
| 93 | |
| 94 | Setup the Certificate Authority |
| 95 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 96 | |
| 97 | This step only needs to be performed once per organization / |
| 98 | organizational unit. First the CA needs a private key. This key must be |
| 99 | kept VERY secret and secure. If this key is compromised the entire trust |
| 100 | chain of the certificates issued with it is lost. |
| 101 | |
| 102 | :: |
| 103 | |
| 104 | # certtool --generate-privkey > ca-key.pem |
| 105 | |
| 106 | To generate a self-signed certificate requires one core piece of |
| 107 | information, the name of the organization. A template file ``ca.info`` |
| 108 | should be populated with the desired data to avoid having to deal with |
| 109 | interactive prompts from certtool:: |
| 110 | |
| 111 | # cat > ca.info <<EOF |
| 112 | cn = Name of your organization |
| 113 | ca |
| 114 | cert_signing_key |
| 115 | EOF |
| 116 | # certtool --generate-self-signed \ |
| 117 | --load-privkey ca-key.pem \ |
| 118 | --template ca.info \ |
| 119 | --outfile ca-cert.pem |
| 120 | |
| 121 | The ``ca`` keyword in the template sets the v3 basic constraints |
| 122 | extension to indicate this certificate is for a CA, while |
| 123 | ``cert_signing_key`` sets the key usage extension to indicate this will |
| 124 | be used for signing other keys. The generated ``ca-cert.pem`` file |
| 125 | should be copied to all servers and clients wishing to utilize TLS |
| 126 | support in the VNC server. The ``ca-key.pem`` must not be |
| 127 | disclosed/copied anywhere except the host responsible for issuing |
| 128 | certificates. |
| 129 | |
| 130 | .. _tls_005fgenerate_005fserver: |
| 131 | |
| 132 | Issuing server certificates |
| 133 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 134 | |
| 135 | Each server (or host) needs to be issued with a key and certificate. |
| 136 | When connecting the certificate is sent to the client which validates it |
| 137 | against the CA certificate. The core pieces of information for a server |
| 138 | certificate are the hostnames and/or IP addresses that will be used by |
| 139 | clients when connecting. The hostname / IP address that the client |
| 140 | specifies when connecting will be validated against the hostname(s) and |
| 141 | IP address(es) recorded in the server certificate, and if no match is |
| 142 | found the client will close the connection. |
| 143 | |
| 144 | Thus it is recommended that the server certificate include both the |
| 145 | fully qualified and unqualified hostnames. If the server will have |
| 146 | permanently assigned IP address(es), and clients are likely to use them |
| 147 | when connecting, they may also be included in the certificate. Both IPv4 |
| 148 | and IPv6 addresses are supported. Historically certificates only |
| 149 | included 1 hostname in the ``CN`` field, however, usage of this field |
| 150 | for validation is now deprecated. Instead modern TLS clients will |
| 151 | validate against the Subject Alt Name extension data, which allows for |
| 152 | multiple entries. In the future usage of the ``CN`` field may be |
| 153 | discontinued entirely, so providing SAN extension data is strongly |
| 154 | recommended. |
| 155 | |
| 156 | On the host holding the CA, create template files containing the |
| 157 | information for each server, and use it to issue server certificates. |
| 158 | |
| 159 | :: |
| 160 | |
| 161 | # cat > server-hostNNN.info <<EOF |
| 162 | organization = Name of your organization |
| 163 | cn = hostNNN.foo.example.com |
| 164 | dns_name = hostNNN |
| 165 | dns_name = hostNNN.foo.example.com |
| 166 | ip_address = 10.0.1.87 |
| 167 | ip_address = 192.8.0.92 |
| 168 | ip_address = 2620:0:cafe::87 |
| 169 | ip_address = 2001:24::92 |
| 170 | tls_www_server |
| 171 | signing_key |
| 172 | EOF |
| 173 | # certtool --generate-privkey > server-hostNNN-key.pem |
| 174 | # certtool --generate-certificate \ |
| 175 | --load-ca-certificate ca-cert.pem \ |
| 176 | --load-ca-privkey ca-key.pem \ |
| 177 | --load-privkey server-hostNNN-key.pem \ |
| 178 | --template server-hostNNN.info \ |
| 179 | --outfile server-hostNNN-cert.pem |
| 180 | |
| 181 | The ``dns_name`` and ``ip_address`` fields in the template are setting |
| 182 | the subject alt name extension data. The ``tls_www_server`` keyword is |
| 183 | the key purpose extension to indicate this certificate is intended for |
| 184 | usage in a web server. Although QEMU network services are not in fact |
| 185 | HTTP servers (except for VNC websockets), setting this key purpose is |
| 186 | still recommended. The ``signing_key`` keyword is the key usage extension |
| 187 | to indicate this certificate is intended for usage in the data session. |
| 188 | |
| 189 | The ``server-hostNNN-key.pem`` and ``server-hostNNN-cert.pem`` files |
| 190 | should now be securely copied to the server for which they were |
| 191 | generated, and renamed to ``server-key.pem`` and ``server-cert.pem`` |
| 192 | when added to the ``/etc/pki/qemu`` directory on the target host. The |
| 193 | ``server-key.pem`` file is security sensitive and should be kept |
| 194 | protected with file mode 0600 to prevent disclosure. |
| 195 | |
| 196 | .. _tls_005fgenerate_005fclient: |
| 197 | |
| 198 | Issuing client certificates |
| 199 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 200 | |
| 201 | The QEMU x509 TLS credential setup defaults to enabling client |
| 202 | verification using certificates, providing a simple authentication |
| 203 | mechanism. If this default is used, each client also needs to be issued |
| 204 | a certificate. The client certificate contains enough metadata to |
| 205 | uniquely identify the client with the scope of the certificate |
| 206 | authority. The client certificate would typically include fields for |
| 207 | organization, state, city, building, etc. |
| 208 | |
| 209 | Once again on the host holding the CA, create template files containing |
| 210 | the information for each client, and use it to issue client |
| 211 | certificates. |
| 212 | |
| 213 | :: |
| 214 | |
| 215 | # cat > client-hostNNN.info <<EOF |
| 216 | country = GB |
| 217 | state = London |
| 218 | locality = City Of London |
| 219 | organization = Name of your organization |
| 220 | cn = hostNNN.foo.example.com |
| 221 | tls_www_client |
| 222 | signing_key |
| 223 | EOF |
| 224 | # certtool --generate-privkey > client-hostNNN-key.pem |
| 225 | # certtool --generate-certificate \ |
| 226 | --load-ca-certificate ca-cert.pem \ |
| 227 | --load-ca-privkey ca-key.pem \ |
| 228 | --load-privkey client-hostNNN-key.pem \ |
| 229 | --template client-hostNNN.info \ |
| 230 | --outfile client-hostNNN-cert.pem |
| 231 | |
| 232 | The subject alt name extension data is not required for clients, so |
| 233 | the ``dns_name`` and ``ip_address`` fields are not included. The |
| 234 | ``tls_www_client`` keyword is the key purpose extension to indicate this |
| 235 | certificate is intended for usage in a web client. Although QEMU network |
| 236 | clients are not in fact HTTP clients, setting this key purpose is still |
| 237 | recommended. The ``signing_key`` keyword is the key usage extension to |
| 238 | indicate this certificate is intended for usage in the data session. |
| 239 | |
| 240 | The ``client-hostNNN-key.pem`` and ``client-hostNNN-cert.pem`` files |
| 241 | should now be securely copied to the client for which they were |
| 242 | generated, and renamed to ``client-key.pem`` and ``client-cert.pem`` |
| 243 | when added to the ``/etc/pki/qemu`` directory on the target host. The |
| 244 | ``client-key.pem`` file is security sensitive and should be kept |
| 245 | protected with file mode 0600 to prevent disclosure. |
| 246 | |
| 247 | If a single host is going to be using TLS in both a client and server |
| 248 | role, it is possible to create a single certificate to cover both roles. |
| 249 | This would be quite common for the migration and NBD services, where a |
| 250 | QEMU process will be started by accepting a TLS protected incoming |
| 251 | migration, and later itself be migrated out to another host. To generate |
| 252 | a single certificate, simply include the template data from both the |
| 253 | client and server instructions in one. |
| 254 | |
| 255 | :: |
| 256 | |
| 257 | # cat > both-hostNNN.info <<EOF |
| 258 | country = GB |
| 259 | state = London |
| 260 | locality = City Of London |
| 261 | organization = Name of your organization |
| 262 | cn = hostNNN.foo.example.com |
| 263 | dns_name = hostNNN |
| 264 | dns_name = hostNNN.foo.example.com |
| 265 | ip_address = 10.0.1.87 |
| 266 | ip_address = 192.8.0.92 |
| 267 | ip_address = 2620:0:cafe::87 |
| 268 | ip_address = 2001:24::92 |
| 269 | tls_www_server |
| 270 | tls_www_client |
| 271 | signing_key |
| 272 | EOF |
| 273 | # certtool --generate-privkey > both-hostNNN-key.pem |
| 274 | # certtool --generate-certificate \ |
| 275 | --load-ca-certificate ca-cert.pem \ |
| 276 | --load-ca-privkey ca-key.pem \ |
| 277 | --load-privkey both-hostNNN-key.pem \ |
| 278 | --template both-hostNNN.info \ |
| 279 | --outfile both-hostNNN-cert.pem |
| 280 | |
| 281 | When copying the PEM files to the target host, save them twice, once as |
| 282 | ``server-cert.pem`` and ``server-key.pem``, and again as |
| 283 | ``client-cert.pem`` and ``client-key.pem``. |
| 284 | |
| 285 | .. _tls_005fcreds_005fsetup: |
| 286 | |
| 287 | TLS x509 credential configuration |
| 288 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 289 | |
| 290 | QEMU has a standard mechanism for loading x509 credentials that will be |
| 291 | used for network services and clients. It requires specifying the |
| 292 | ``tls-creds-x509`` class name to the ``--object`` command line argument |
| 293 | for the system emulators. Each set of credentials loaded should be given |
| 294 | a unique string identifier via the ``id`` parameter. A single set of TLS |
| 295 | credentials can be used for multiple network backends, so VNC, |
| 296 | migration, NBD, character devices can all share the same credentials. |
| 297 | Note, however, that credentials for use in a client endpoint must be |
| 298 | loaded separately from those used in a server endpoint. |
| 299 | |
| 300 | When specifying the object, the ``dir`` parameters specifies which |
| 301 | directory contains the credential files. This directory is expected to |
| 302 | contain files with the names mentioned previously, ``ca-cert.pem``, |
| 303 | ``server-key.pem``, ``server-cert.pem``, ``client-key.pem`` and |
| 304 | ``client-cert.pem`` as appropriate. |
| 305 | |
| 306 | While it is possible to include a set of pre-generated Diffie-Hellman |
| 307 | (DH) parameters in a file ``dh-params.pem``, this facility is now |
| 308 | deprecated and will be removed in a future release. When omitted the |
| 309 | DH parameters will be automatically negotiated in accordance with |
| 310 | RFC7919. |
| 311 | |
| 312 | The ``endpoint`` parameter indicates whether the credentials will be |
| 313 | used for a network client or server, and determines which PEM files are |
| 314 | loaded. |
| 315 | |
| 316 | The ``verify`` parameter determines whether x509 certificate validation |
| 317 | should be performed. This defaults to enabled, meaning clients will |
| 318 | always validate the server hostname against the certificate subject alt |
| 319 | name fields and/or CN field. It also means that servers will request |
| 320 | that clients provide a certificate and validate them. Verification |
| 321 | should never be turned off for client endpoints, however, it may be |
| 322 | turned off for server endpoints if an alternative mechanism is used to |
| 323 | authenticate clients. For example, the VNC server can use SASL to |
| 324 | authenticate clients instead. |
| 325 | |
| 326 | To load server credentials with client certificate validation enabled |
| 327 | |
| 328 | .. parsed-literal:: |
| 329 | |
| 330 | |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=server |
| 331 | |
| 332 | while to load client credentials use |
| 333 | |
| 334 | .. parsed-literal:: |
| 335 | |
| 336 | |qemu_system| -object tls-creds-x509,id=tls0,dir=/etc/pki/qemu,endpoint=client |
| 337 | |
| 338 | Network services which support TLS will all have a ``tls-creds`` |
| 339 | parameter which expects the ID of the TLS credentials object. For |
| 340 | example with VNC: |
| 341 | |
| 342 | .. parsed-literal:: |
| 343 | |
| 344 | |qemu_system| -vnc 0.0.0.0:0,tls-creds=tls0 |
| 345 | |
| 346 | .. _tls_005fpsk: |
| 347 | |
| 348 | TLS certificates for Post-Quantum Cryptography |
| 349 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 350 | |
| 351 | Given a new enough gnutls release, suitably integrated & configured with the |
| 352 | operating system crypto policies, QEMU is able to support post-quantum |
| 353 | cryptography on TLS enabled services, either exclusively or in a hybrid mode. |
| 354 | |
| 355 | In exclusive mode, only a single set of certificates need to be configured |
| 356 | for QEMU, with PQC compliant algorithms. Such a QEMU configuration will only |
| 357 | be able to interoperate with other services (including other QEMU's) that |
| 358 | also have PQC enabled. This can result in compatibility concerns during the |
| 359 | period of transition over to PQC compliant algorithms. |
| 360 | |
| 361 | In hybrid mode, multiple sets of certificates need to be configured for QEMU, |
| 362 | at least one set with traditional (non-PQC compliant) algorithms, and at least |
| 363 | one other set with modern (PQC compliant) algorithms. At time of the TLS |
| 364 | handshake, the GNUTLS algorithm priorities should ensure that PQC compliant |
| 365 | algorithms are negotiated if both sides of the connection support PQC. If one |
| 366 | side lacks PQC, the TLS handshake should fallback to the non-PQC algorithms. |
| 367 | This can assist with interoperability during the transition to PQC, but has a |
| 368 | potential weakness wrt downgrade attacks forcing use of non-PQC algorithms. |
| 369 | Exclusive PQC mode should be preferred where both peers in the TLS connections |
| 370 | are known to support PQC. |
| 371 | |
| 372 | Key generation parameters |
| 373 | ^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 374 | |
| 375 | To create certificates with PQC compliant algorithms, the ``--key-type`` |
| 376 | argument must be passed to ``certtool`` when creating private keys. No |
| 377 | extra arguments are required for the other ``certtool`` commands, as |
| 378 | their behaviour will be determined by the private key type. |
| 379 | |
| 380 | The typical PQC compliant algorithms to use are ``ML-DSA-44``, ``ML-DSA-65`` |
| 381 | and ``ML-DSA-87``, with ``ML-DSA-65`` being a suitable default choice in |
| 382 | the absence of explicit requirements. |
| 383 | |
| 384 | Taking the example earlier, for creating a key for a client certificate, |
| 385 | to use ``ML-DSA-65`` the command line would be modified to look like:: |
| 386 | |
| 387 | # certtool --generate-privkey --key-type=mldsa65 > client-hostNNN-key.pem |
| 388 | |
| 389 | The equivalent modification applies to the creation of the private keys |
| 390 | used for server certs, or root/intermediate CA certs. |
| 391 | |
| 392 | For hybrid mode, the additional indexed certificate naming must be used. |
| 393 | If multiple configured certificates are compatible with the mutually |
| 394 | supported crypto algorithms between the client and server, then the |
| 395 | first matching certificate will be used. |
| 396 | |
| 397 | IOW, to ensure that PQC certificates are preferred, they must use a |
| 398 | non-index based filename, or use an index that is smaller than any |
| 399 | non-PQC certificates. ie, ``server-cert.pem`` for PQC and ``server-cert-0.pem`` |
| 400 | for non-PQC, or ``server-cert-0.pem`` for PQC and ``server-cert-1.pem`` for |
| 401 | non-PQC. |
| 402 | |
| 403 | Force disabling PQC via crypto priority |
| 404 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 405 | |
| 406 | In the OS configuration for system crypto algorithm priorities has |
| 407 | enabled PQC, this can (optionally) be overridden in QEMU configuration |
| 408 | disable use of PQC using the ``priority`` parameter to the ``tls-creds-x509`` |
| 409 | object:: |
| 410 | |
| 411 | NO_MLDSA="-SIGN-ML-DSA-65:-SIGN-ML-DSA-44:-SIGN-ML-DSA-87" |
| 412 | NO_MLKEM="-GROUP-X25519-MLKEM768:-GROUP-SECP256R1-MLKEM768:-GROUP-SECP384R1-MLKEM1024" |
| 413 | # qemu-nbd --object tls-creds-x509,id=tls0,endpoint=server,dir=....,priority=@SYSTEM:$NO_MLDSA:$NO_MLKEM |
| 414 | |
| 415 | |
| 416 | TLS Pre-Shared Keys (PSK) |
| 417 | ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 418 | |
| 419 | Instead of using certificates, you may also use TLS Pre-Shared Keys |
| 420 | (TLS-PSK). This can be simpler to set up than certificates but is less |
| 421 | scalable. |
| 422 | |
| 423 | Use the GnuTLS ``psktool`` program to generate a ``keys.psk`` file |
| 424 | containing one or more usernames and random keys:: |
| 425 | |
| 426 | mkdir -m 0700 /tmp/keys |
| 427 | psktool -u rich -p /tmp/keys/keys.psk |
| 428 | |
| 429 | TLS-enabled servers such as ``qemu-nbd`` can use this directory like so:: |
| 430 | |
| 431 | qemu-nbd \ |
| 432 | -t -x / \ |
| 433 | --object tls-creds-psk,id=tls0,endpoint=server,dir=/tmp/keys \ |
| 434 | --tls-creds tls0 \ |
| 435 | image.qcow2 |
| 436 | |
| 437 | When connecting from a qemu-based client you must specify the directory |
| 438 | containing ``keys.psk`` and an optional username (defaults to "qemu"):: |
| 439 | |
| 440 | qemu-img info \ |
| 441 | --object tls-creds-psk,id=tls0,dir=/tmp/keys,username=rich,endpoint=client \ |
| 442 | --image-opts \ |
| 443 | file.driver=nbd,file.host=localhost,file.port=10809,file.tls-creds=tls0,file.export=/ |