diff options
Diffstat (limited to 'crypto/tlssession.c')
-rw-r--r-- | crypto/tlssession.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/crypto/tlssession.c b/crypto/tlssession.c index 96a02deb69..66a6fbe19c 100644 --- a/crypto/tlssession.c +++ b/crypto/tlssession.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "crypto/tlssession.h" #include "crypto/tlscredsanon.h" +#include "crypto/tlscredspsk.h" #include "crypto/tlscredsx509.h" #include "qapi/error.h" #include "qemu/acl.h" @@ -88,6 +89,14 @@ qcrypto_tls_session_pull(void *opaque, void *buf, size_t len) return session->readFunc(buf, len, session->opaque); } +#define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH" + +#if GNUTLS_VERSION_MAJOR >= 3 +#define TLS_ECDHE_PSK "+ECDHE-PSK:" +#else +#define TLS_ECDHE_PSK "" +#endif +#define TLS_PRIORITY_ADDITIONAL_PSK TLS_ECDHE_PSK "+DHE-PSK:+PSK" QCryptoTLSSession * qcrypto_tls_session_new(QCryptoTLSCreds *creds, @@ -135,9 +144,12 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds, char *prio; if (creds->priority != NULL) { - prio = g_strdup_printf("%s:+ANON-DH", creds->priority); + prio = g_strdup_printf("%s:%s", + creds->priority, + TLS_PRIORITY_ADDITIONAL_ANON); } else { - prio = g_strdup(CONFIG_TLS_PRIORITY ":+ANON-DH"); + prio = g_strdup(CONFIG_TLS_PRIORITY ":" + TLS_PRIORITY_ADDITIONAL_ANON); } ret = gnutls_priority_set_direct(session->handle, prio, NULL); @@ -163,6 +175,42 @@ qcrypto_tls_session_new(QCryptoTLSCreds *creds, goto error; } } else if (object_dynamic_cast(OBJECT(creds), + TYPE_QCRYPTO_TLS_CREDS_PSK)) { + QCryptoTLSCredsPSK *pcreds = QCRYPTO_TLS_CREDS_PSK(creds); + char *prio; + + if (creds->priority != NULL) { + prio = g_strdup_printf("%s:%s", + creds->priority, + TLS_PRIORITY_ADDITIONAL_PSK); + } else { + prio = g_strdup(CONFIG_TLS_PRIORITY ":" + TLS_PRIORITY_ADDITIONAL_PSK); + } + + ret = gnutls_priority_set_direct(session->handle, prio, NULL); + if (ret < 0) { + error_setg(errp, "Unable to set TLS session priority %s: %s", + prio, gnutls_strerror(ret)); + g_free(prio); + goto error; + } + g_free(prio); + if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) { + ret = gnutls_credentials_set(session->handle, + GNUTLS_CRD_PSK, + pcreds->data.server); + } else { + ret = gnutls_credentials_set(session->handle, + GNUTLS_CRD_PSK, + pcreds->data.client); + } + if (ret < 0) { + error_setg(errp, "Cannot set session credentials: %s", + gnutls_strerror(ret)); + goto error; + } + } else if (object_dynamic_cast(OBJECT(creds), TYPE_QCRYPTO_TLS_CREDS_X509)) { QCryptoTLSCredsX509 *tcreds = QCRYPTO_TLS_CREDS_X509(creds); const char *prio = creds->priority; @@ -354,6 +402,10 @@ qcrypto_tls_session_check_credentials(QCryptoTLSSession *session, trace_qcrypto_tls_session_check_creds(session, "nop"); return 0; } else if (object_dynamic_cast(OBJECT(session->creds), + TYPE_QCRYPTO_TLS_CREDS_PSK)) { + trace_qcrypto_tls_session_check_creds(session, "nop"); + return 0; + } else if (object_dynamic_cast(OBJECT(session->creds), TYPE_QCRYPTO_TLS_CREDS_X509)) { if (session->creds->verifyPeer) { int ret = qcrypto_tls_session_check_certificate(session, |