Daniel P. Berrangé <berra...@redhat.com> writes:

> 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é <berra...@redhat.com>

Hi, the CI caught a couple of issues. I'll fixup on the branch, no need
to resend.

...

> +void qcrypto_tls_session_require_thread_safety(QCryptoTLSSession *sess)
> +{
> +    sess->requireThreadSafety = true;
> +}

Needs a stub.

...

> @@ -545,8 +600,29 @@ int
>  qcrypto_tls_session_handshake(QCryptoTLSSession *session,
>                                Error **errp)
>  {
> -    int ret = gnutls_handshake(session->handle);
> +    int ret;
> +    ret = gnutls_handshake(session->handle);
> +
>      if (!ret) {
> +        gnutls_cipher_algorithm_t cipher =
> +            gnutls_cipher_get(session->handle);
> +

Unused var when the config is not enabled.

> +#ifdef CONFIG_GNUTLS_BUG1717_WORKAROUND
> +        /*
> +         * Any use of rekeying in TLS 1.3 is unsafe for
> +         * a gnutls with bug 1717, however, we know that
> +         * QEMU won't initiate manual rekeying. Thus we
> +         * only have to protect against automatic rekeying
> +         * which doesn't trigger with CHACHA20
> +         */
> +        if (session->requireThreadSafety &&
> +            gnutls_protocol_get_version(session->handle) ==
> +            GNUTLS_TLS1_3 &&
> +            cipher != GNUTLS_CIPHER_CHACHA20_POLY1305) {
> +            session->lockEnabled = true;
> +        }
> +#endif
> +
>          session->handshakeComplete = true;
>          return QCRYPTO_TLS_HANDSHAKE_COMPLETE;
>      }

Reply via email to