summary refs log tree commit diff stats
path: root/crypto/tlssession.c (follow)
Commit message (Collapse)AuthorAgeFilesLines
* io/crypto: Move tls premature termination handling into QIO layerPeter Xu2025-10-031-5/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QCryptoTLSSession allows TLS premature termination in two cases, one of the case is when the channel shutdown() is invoked on READ side. It's possible the shutdown() happened after the read thread blocked at gnutls_record_recv(). In this case, we should allow the premature termination to happen. The problem is by the time qcrypto_tls_session_read() was invoked, tioc->shutdown may not have been set, so this may instead be treated as an error if there is concurrent shutdown() calls. To allow the flag to reflect the latest status of tioc->shutdown, move the check upper into the QIOChannel level, so as to read the flag only after QEMU gets an GNUTLS_E_PREMATURE_TERMINATION. When at it, introduce qio_channel_tls_allow_premature_termination() helper to make the condition checks easier to read. When doing so, change the qatomic_load_acquire() to qatomic_read(): here we don't need any ordering of memory accesses, but reading a flag. qatomic_read() would suffice because it guarantees fetching from memory. Nothing else we should need to order on memory access. This patch will fix a qemu qtest warning when running the preempt tls test, reporting premature termination: QTEST_QEMU_BINARY=./qemu-system-x86_64 ./tests/qtest/migration-test --full -r /x86_64/migration/postcopy/preempt/tls/psk ... qemu-kvm: Cannot read from TLS channel: The TLS connection was non-properly terminated. ... In this specific case, the error was set by postcopy_preempt_thread, which normally will be concurrently shutdown()ed by the main thread. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20250918203937.200833-2-peterx@redhat.com Signed-off-by: Peter Xu <peterx@redhat.com>
* crypto: add tracing & warning about GNUTLS countermeasuresDaniel P. Berrangé2025-07-221-0/+11
| | | | | | | | | | | | | | | We want some visibility on stderr when the GNUTLS thread safety countermeasures are activated, to encourage people to get the real fix deployed (once it exists). Some trace points will also help if we see any further wierd crash scenario we've not anticipated. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/qemu-devel/20250718150514.2635338-5-berrange@redhat.com [add missing include] Signed-off-by: Fabiano Rosas <farosas@suse.de>
* crypto: implement workaround for GNUTLS thread safety problemsDaniel P. Berrangé2025-07-221-3/+89
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When TLS 1.3 is negotiated on a TLS session, GNUTLS will perform automatic rekeying of the session after 16 million records. This is done for all algorithms except CHACHA20_POLY1305 which does not require rekeying. Unfortunately the rekeying breaks GNUTLS' promise that it is safe to use a gnutls_session_t object concurrently from multiple threads if they are exclusively calling gnutls_record_send/recv. This patch implements a workaround for QEMU that adds a mutex lock around any gnutls_record_send/recv call to serialize execution within GNUTLS code. When GNUTLS calls into the push/pull functions we can release the lock so the OS level I/O calls can at least have some parallelism. The big downside of this is that the actual encryption/decryption code is fully serialized, which will halve performance of that cipher operations if two threads are contending. The workaround is not enabled by default, since most use of GNUTLS in QEMU does not tickle the problem, only non-multifd migration with a return path open is affected. Fortunately the migration code also won't trigger the halving of performance, since only the outbound channel diretion needs to sustain high data rates, the inbound direction is low volume. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/qemu-devel/20250718150514.2635338-2-berrange@redhat.com [add stub for qcrypto_tls_session_require_thread_safety; fix unused var] Signed-off-by: Fabiano Rosas <farosas@suse.de>
* crypto: Remove qcrypto_tls_session_get_handshake_statusFabiano Rosas2025-02-141-36/+19
| | | | | | | | | | | | | | | | The correct way of calling qcrypto_tls_session_handshake() requires calling qcrypto_tls_session_get_handshake_status() right after it so there's no reason to have a separate method. Refactor qcrypto_tls_session_handshake() to inform the status in its own return value and alter the callers accordingly. No functional change. Suggested-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Acked-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de>
* crypto: Allow gracefully ending the TLS sessionFabiano Rosas2025-02-141-0/+41
| | | | | | | | | | | | | | | | | | | QEMU's TLS session code provides no way to call gnutls_bye() to terminate a TLS session. Callers of qcrypto_tls_session_read() can choose to ignore a GNUTLS_E_PREMATURE_TERMINATION error by setting the gracefulTermination argument. The QIOChannelTLS ignores the premature termination error whenever shutdown() has already been issued. This was found to be not enough for the migration code because shutdown() might not have been issued before the connection is terminated. Add support for calling gnutls_bye() in the tlssession layer so users of QIOChannelTLS can clearly identify the end of a TLS session. Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Acked-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de>
* crypto: propagate errors from TLS session I/O callbacksDaniel P. Berrangé2024-07-241-10/+66
| | | | | | | | | | | | | | | GNUTLS doesn't know how to perform I/O on anything other than plain FDs, so the TLS session provides it with some I/O callbacks. The GNUTLS API design requires these callbacks to return a unix errno value, which means we're currently loosing the useful QEMU "Error" object. This changes the I/O callbacks in QEMU to stash the "Error" object in the QCryptoTLSSession class, and fetch it when seeing an I/O error returned from GNUTLS, thus preserving useful error messages. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: push error reporting into TLS session I/O APIsDaniel P. Berrangé2024-07-241-31/+29
| | | | | | | | | | | | | The current TLS session I/O APIs just return a synthetic errno value on error, which has been translated from a gnutls error value. This looses a large amount of valuable information that distinguishes different scenarios. Pushing population of the "Error *errp" object into the TLS session I/O APIs gives more detailed error information. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: TLS: introduce `check_pending`Antoine Damhet2023-02-151-0/+14
| | | | | | | | | The new `qcrypto_tls_session_check_pending` function allows the caller to know if data have already been consumed from the backend and is already available. Signed-off-by: Antoine Damhet <antoine.damhet@shadow.tech> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: mandate a hostname when checking x509 creds on a clientDaniel P. Berrangé2022-03-071-0/+6
| | | | | | | | | | | | | | | | | | Currently the TLS session object assumes that the caller will always provide a hostname when using x509 creds on a client endpoint. This relies on the caller to detect and report an error if the user has configured QEMU with x509 credentials on a UNIX socket. The migration code has such a check, but it is too broad, reporting an error when the user has configured QEMU with PSK credentials on a UNIX socket, where hostnames are irrelevant. Putting the check into the TLS session object credentials validation code ensures we report errors in only the scenario that matters. Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Message-Id: <20220304193610.3293146-2-berrange@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
* crypto: Make QCryptoTLSCreds* structures privatePhilippe Mathieu-Daudé2021-06-291-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Code consuming the "crypto/tlscreds*.h" APIs doesn't need to access its internals. Move the structure definitions to the "tlscredspriv.h" private header (only accessible by implementations). The public headers (in include/) still forward-declare the structures typedef. Note, tlscreds.c and 3 of the 5 modified source files already include "tlscredspriv.h", so only add it to tls-cipher-suites.c and tlssession.c. Removing the internals from the public header solves a bug introduced by commit 7de2e856533 ("yank: Unregister function when using TLS migration") which made migration/qemu-file-channel.c include "io/channel-tls.h", itself sometime depends on GNUTLS, leading to a build failure on OSX: [2/35] Compiling C object libmigration.fa.p/migration_qemu-file-channel.c.o FAILED: libmigration.fa.p/migration_qemu-file-channel.c.o cc -Ilibmigration.fa.p -I. -I.. -Iqapi [ ... ] -o libmigration.fa.p/migration_qemu-file-channel.c.o -c ../migration/qemu-file-channel.c In file included from ../migration/qemu-file-channel.c:29: In file included from include/io/channel-tls.h:26: In file included from include/crypto/tlssession.h:24: include/crypto/tlscreds.h:28:10: fatal error: 'gnutls/gnutls.h' file not found #include <gnutls/gnutls.h> ^~~~~~~~~~~~~~~~~ 1 error generated. Reported-by: Stefan Weil <sw@weilnetz.de> Suggested-by: Daniel P. Berrangé <berrange@redhat.com> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/407 Fixes: 7de2e856533 ("yank: Unregister function when using TLS migration") Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: Fix LGPL information in the file headersThomas Huth2019-07-191-1/+1
| | | | | | | | | It's either "GNU *Library* General Public License version 2" or "GNU Lesser General Public License version *2.1*", but there was no "version 2.0" of the "Lesser" license. So assume that version 2.1 is meant here. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* authz: delete existing ACL implementationDaniel P. Berrange2019-02-261-18/+17
| | | | | | | | | | | | | | | | The 'qemu_acl' type was a previous non-QOM based attempt to provide an authorization facility in QEMU. Because it is non-QOM based it cannot be created via the command line and requires special monitor commands to manipulate it. The new QAuthZ subclasses provide a superset of the functionality in qemu_acl, so the latter can now be deleted. The HMP 'acl_*' monitor commands are converted to use the new QAuthZSimple data type instead in order to provide temporary backwards compatibility. Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
* io: return 0 for EOF in TLS session read after shutdownDaniel P. Berrangé2018-11-191-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | GNUTLS takes a paranoid approach when seeing 0 bytes returned by the underlying OS read() function. It will consider this an error and return GNUTLS_E_PREMATURE_TERMINATION instead of propagating the 0 return value. It expects apps to arrange for clean termination at the protocol level and not rely on seeing EOF from a read call to detect shutdown. This is to harden apps against a malicious 3rd party causing termination of the sockets layer. This is unhelpful for the QEMU NBD code which does have a clean protocol level shutdown, but still relies on seeing 0 from the I/O channel read in the coroutine handling incoming replies. The upshot is that when using a plain NBD connection shutdown is silent, but when using TLS, the client spams the console with Cannot read from TLS channel: Broken pipe The NBD connection has, however, called qio_channel_shutdown() at this point to indicate that it is done with I/O. This gives the opportunity to optimize the code such that when the channel has been shutdown in the read direction, the error code GNUTLS_E_PREMATURE_TERMINATION gets turned into a '0' return instead of an error. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> Message-Id: <20181119134228.11031-1-berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
* crypto: require gnutls >= 3.1.18 for building QEMUDaniel P. Berrangé2018-10-191-7/+1
| | | | | | | | | | | | | | | | | | | | | | | gnutls 3.0.0 was released in 2011 and all the distros that are build target platforms for QEMU [1] include it: RHEL-7: 3.1.18 Debian (Stretch): 3.5.8 Debian (Jessie): 3.3.8 OpenBSD (ports): 3.5.18 FreeBSD (ports): 3.5.18 OpenSUSE Leap 15: 3.6.2 Ubuntu (Xenial): 3.4.10 macOS (Homebrew): 3.5.19 Based on this, it is reasonable to require gnutls >= 3.1.18 in QEMU which allows for all conditional version checks in the code to be removed. [1] https://qemu.weilnetz.de/doc/qemu-doc.html#Supported-build-platforms Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: Implement TLS Pre-Shared Keys (PSK).Richard W.M. Jones2018-07-031-2/+54
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Pre-Shared Keys (PSK) is a simpler mechanism for enabling TLS connections than using certificates. It requires only a simple secret key: $ mkdir -m 0700 /tmp/keys $ psktool -u rjones -p /tmp/keys/keys.psk $ cat /tmp/keys/keys.psk rjones:d543770c15ad93d76443fb56f501a31969235f47e999720ae8d2336f6a13fcbc The key can be secretly shared between clients and servers. Clients must specify the directory containing the "keys.psk" file and a username (defaults to "qemu"). Servers must specify only the directory. Example NBD client: $ qemu-img info \ --object tls-creds-psk,id=tls0,dir=/tmp/keys,username=rjones,endpoint=client \ --image-opts \ file.driver=nbd,file.host=localhost,file.port=10809,file.tls-creds=tls0,file.export=/ Example NBD server using qemu-nbd: $ qemu-nbd -t -x / \ --object tls-creds-psk,id=tls0,endpoint=server,dir=/tmp/keys \ --tls-creds tls0 \ image.qcow2 Example NBD server using nbdkit: $ nbdkit -n -e / -fv \ --tls=on --tls-psk=/tmp/keys/keys.psk \ file file=disk.img Signed-off-by: Richard W.M. Jones <rjones@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
* crypto: add trace points for TLS cert verificationDaniel P. Berrange2016-09-191-2/+8
| | | | | | | It is very useful to know about TLS cert verification status when debugging, so add a trace point for it. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
* crypto: allow default TLS priority to be chosen at build timeDaniel P. Berrange2016-07-041-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Modern gnutls can use a global config file to control the crypto priority settings for TLS connections. For example the priority string "@SYSTEM" instructs gnutls to find the priority setting named "SYSTEM" in the global config file. Latest gnutls GIT codebase gained the ability to reference multiple priority strings in the config file, with the first one that is found to existing winning. This means it is now possible to configure QEMU out of the box with a default priority of "@QEMU,SYSTEM", which says to look for the settings "QEMU" first, and if not found, use the "SYSTEM" settings. To make use of this facility, we introduce the ability to set the QEMU default priority at build time via a new configure argument. It is anticipated that distro vendors will set this when building QEMU to a suitable value for use with distro crypto policy setup. eg current Fedora would run ./configure --tls-priority=@SYSTEM while future Fedora would run ./configure --tls-priority=@QEMU,SYSTEM Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
* crypto: add support for TLS priority string overrideDaniel P. Berrange2016-07-041-7/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The gnutls default priority is either "NORMAL" (most historical versions of gnutls) which is a built-in label in gnutls code, or "@SYSTEM" (latest gnutls on Fedora at least) which refers to an admin customizable entry in a gnutls config file. Regardless of which default is used by a distro, they are both global defaults applying to all applications using gnutls. If a single application on the system needs to use a weaker set of crypto priorities, this potentially forces the weakness onto all applications. Or conversely if a single application wants a strong default than all others, it can't do this via the global config file. This adds an extra parameter to the tls credential object which allows the mgmt app / user to explicitly provide a priority string to QEMU when configuring TLS. For example, to use the "NORMAL" priority, but disable SSL 3.0 one can now configure QEMU thus: $QEMU -object tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\ priority="NORMAL:-VERS-SSL3.0" \ ..other args... If creating tls-creds-anon, whatever priority the user specifies will always have "+ANON-DH" appended to it, since that's mandatory to make the anonymous credentials work. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
* include/qemu/osdep.h: Don't include qapi/error.hMarkus Armbruster2016-03-221-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the Error typedef. Since then, we've moved to include qemu/osdep.h everywhere. Its file comment explains: "To avoid getting into possible circular include dependencies, this file should not include any other QEMU headers, with the exceptions of config-host.h, compiler.h, os-posix.h and os-win32.h, all of which are doing a similar job to this file and are under similar constraints." qapi/error.h doesn't do a similar job, and it doesn't adhere to similar constraints: it includes qapi-types.h. That's in excess of 100KiB of crap most .c files don't actually need. Add the typedef to qemu/typedefs.h, and include that instead of qapi/error.h. Include qapi/error.h in .c files that need it and don't get it now. Include qapi-types.h in qom/object.h for uint16List. Update scripts/clean-includes accordingly. Update it further to match reality: replace config.h by config-target.h, add sysemu/os-posix.h, sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h comment quoted above similarly. This reduces the number of objects depending on qapi/error.h from "all of them" to less than a third. Unfortunately, the number depending on qapi-types.h shrinks only a little. More work is needed for that one. Signed-off-by: Markus Armbruster <armbru@redhat.com> [Fix compilation without the spice devel packages. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
* crypto: Clean up includesPeter Maydell2016-01-291-0/+1
| | | | | | | | | | Clean up includes so that osdep.h is included first and headers which it implies are not included manually. This commit was created with scripts/clean-includes. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1453832250-766-3-git-send-email-peter.maydell@linaro.org
* crypto: fix mistaken setting of Error in success code pathDaniel P. Berrange2015-11-181-2/+2
| | | | | | | | | | | The qcrypto_tls_session_check_certificate() method was setting an Error even when the ACL check suceeded. This didn't affect the callers detection of errors because they relied on the function return status, but this did cause a memory leak since the caller would not free an Error they did not expect to be set. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
* crypto: introduce new module for handling TLS sessionsDaniel P. Berrange2015-09-151-0/+574
Introduce a QCryptoTLSSession object that will encapsulate all the code for setting up and using a client/sever TLS session. This isolates the code which depends on the gnutls library, avoiding #ifdefs in the rest of the codebase, as well as facilitating any possible future port to other TLS libraries, if desired. It makes use of the previously defined QCryptoTLSCreds object to access credentials to use with the session. It also includes further unit tests to validate the correctness of the TLS session handshake and certificate validation. This is functionally equivalent to the current TLS session handling code embedded in the VNC server, and will obsolete it. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>