aboutsummaryrefslogtreecommitdiff
path: root/crypto/tlssession.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/tlssession.c')
-rw-r--r--crypto/tlssession.c56
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,