QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
#ifdef CONFIG_GNUTLS
- if (creds->dh_params) {
- gnutls_dh_params_deinit(creds->dh_params);
- }
+ qcrypto_tls_creds_box_unref(creds->box);
#endif
-
g_free(creds->dir);
g_free(creds->priority);
}
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
Error **errp)
{
+ g_autoptr(QCryptoTLSCredsBox) box = NULL;
g_autofree char *dhparams = NULL;
int ret;
creds->parent_obj.dir ? creds->parent_obj.dir : "<nodir>");
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_ANON);
+
if (creds->parent_obj.dir &&
qcrypto_tls_creds_get_path(&creds->parent_obj,
QCRYPTO_TLS_CREDS_DH_PARAMS,
return -1;
}
- ret = gnutls_anon_allocate_server_credentials(&creds->data.server);
+ ret = gnutls_anon_allocate_server_credentials(&box->data.anonserver);
if (ret < 0) {
error_setg(errp, "Cannot allocate credentials: %s",
gnutls_strerror(ret));
}
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
- &creds->parent_obj.dh_params,
- errp) < 0) {
+ &box->dh_params, errp) < 0) {
return -1;
}
- gnutls_anon_set_server_dh_params(creds->data.server,
- creds->parent_obj.dh_params);
+ gnutls_anon_set_server_dh_params(box->data.anonserver,
+ box->dh_params);
} else {
- ret = gnutls_anon_allocate_client_credentials(&creds->data.client);
+ ret = gnutls_anon_allocate_client_credentials(&box->data.anonclient);
if (ret < 0) {
error_setg(errp, "Cannot allocate credentials: %s",
gnutls_strerror(ret));
return -1;
}
}
+ creds->parent_obj.box = g_steal_pointer(&box);
return 0;
}
-static void
-qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds)
-{
- if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
- if (creds->data.client) {
- gnutls_anon_free_client_credentials(creds->data.client);
- creds->data.client = NULL;
- }
- } else {
- if (creds->data.server) {
- gnutls_anon_free_server_credentials(creds->data.server);
- creds->data.server = NULL;
- }
- }
-}
-
#else /* ! CONFIG_GNUTLS */
}
-static void
-qcrypto_tls_creds_anon_unload(QCryptoTLSCredsAnon *creds G_GNUC_UNUSED)
-{
- /* nada */
-}
-
-
#endif /* ! CONFIG_GNUTLS */
}
-static void
-qcrypto_tls_creds_anon_finalize(Object *obj)
-{
- QCryptoTLSCredsAnon *creds = QCRYPTO_TLS_CREDS_ANON(obj);
-
- qcrypto_tls_creds_anon_unload(creds);
-}
-
-
static void
qcrypto_tls_creds_anon_class_init(ObjectClass *oc, const void *data)
{
.parent = TYPE_QCRYPTO_TLS_CREDS,
.name = TYPE_QCRYPTO_TLS_CREDS_ANON,
.instance_size = sizeof(QCryptoTLSCredsAnon),
- .instance_finalize = qcrypto_tls_creds_anon_finalize,
.class_size = sizeof(QCryptoTLSCredsAnonClass),
.class_init = qcrypto_tls_creds_anon_class_init,
.interfaces = (const InterfaceInfo[]) {
#define QCRYPTO_TLSCREDSPRIV_H
#include "crypto/tlscreds.h"
+#include "crypto/tlscredsbox.h"
#ifdef CONFIG_GNUTLS
#include <gnutls/gnutls.h>
Object parent_obj;
char *dir;
QCryptoTLSCredsEndpoint endpoint;
-#ifdef CONFIG_GNUTLS
- gnutls_dh_params_t dh_params;
-#endif
bool verifyPeer;
char *priority;
+ QCryptoTLSCredsBox *box;
};
struct QCryptoTLSCredsAnon {
QCryptoTLSCreds parent_obj;
-#ifdef CONFIG_GNUTLS
- union {
- gnutls_anon_server_credentials_t server;
- gnutls_anon_client_credentials_t client;
- } data;
-#endif
};
struct QCryptoTLSCredsPSK {
QCryptoTLSCreds parent_obj;
char *username;
-#ifdef CONFIG_GNUTLS
- union {
- gnutls_psk_server_credentials_t server;
- gnutls_psk_client_credentials_t client;
- } data;
-#endif
};
struct QCryptoTLSCredsX509 {
QCryptoTLSCreds parent_obj;
-#ifdef CONFIG_GNUTLS
- gnutls_certificate_credentials_t data;
-#endif
bool sanityCheck;
char *passwordid;
};
qcrypto_tls_creds_psk_load(QCryptoTLSCredsPSK *creds,
Error **errp)
{
+ g_autoptr(QCryptoTLSCredsBox) box = NULL;
g_autofree char *pskfile = NULL;
g_autofree char *dhparams = NULL;
const char *username;
}
if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_PSK);
+
if (creds->username) {
error_setg(errp, "username should not be set when endpoint=server");
goto cleanup;
goto cleanup;
}
- ret = gnutls_psk_allocate_server_credentials(&creds->data.server);
+ ret = gnutls_psk_allocate_server_credentials(&box->data.pskserver);
if (ret < 0) {
error_setg(errp, "Cannot allocate credentials: %s",
gnutls_strerror(ret));
}
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
- &creds->parent_obj.dh_params,
+ &box->dh_params,
errp) < 0) {
goto cleanup;
}
- ret = gnutls_psk_set_server_credentials_file(creds->data.server, pskfile);
+ ret = gnutls_psk_set_server_credentials_file(box->data.pskserver,
+ pskfile);
if (ret < 0) {
error_setg(errp, "Cannot set PSK server credentials: %s",
gnutls_strerror(ret));
goto cleanup;
}
- gnutls_psk_set_server_dh_params(creds->data.server,
- creds->parent_obj.dh_params);
+ gnutls_psk_set_server_dh_params(box->data.pskserver,
+ box->dh_params);
} else {
+ box = qcrypto_tls_creds_box_new_client(GNUTLS_CRD_PSK);
+
if (qcrypto_tls_creds_get_path(&creds->parent_obj,
QCRYPTO_TLS_CREDS_PSKFILE,
true, &pskfile, errp) < 0) {
goto cleanup;
}
- ret = gnutls_psk_allocate_client_credentials(&creds->data.client);
+ ret = gnutls_psk_allocate_client_credentials(&box->data.pskclient);
if (ret < 0) {
error_setg(errp, "Cannot allocate credentials: %s",
gnutls_strerror(ret));
goto cleanup;
}
- ret = gnutls_psk_set_client_credentials(creds->data.client,
+ ret = gnutls_psk_set_client_credentials(box->data.pskclient,
username, &key, GNUTLS_PSK_KEY_HEX);
if (ret < 0) {
error_setg(errp, "Cannot set PSK client credentials: %s",
goto cleanup;
}
}
+ creds->parent_obj.box = g_steal_pointer(&box);
rv = 0;
cleanup:
return rv;
}
-
-static void
-qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds)
-{
- if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
- if (creds->data.client) {
- gnutls_psk_free_client_credentials(creds->data.client);
- creds->data.client = NULL;
- }
- } else {
- if (creds->data.server) {
- gnutls_psk_free_server_credentials(creds->data.server);
- creds->data.server = NULL;
- }
- }
-}
-
#else /* ! CONFIG_GNUTLS */
}
-static void
-qcrypto_tls_creds_psk_unload(QCryptoTLSCredsPSK *creds G_GNUC_UNUSED)
-{
- /* nada */
-}
-
-
#endif /* ! CONFIG_GNUTLS */
{
QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);
- qcrypto_tls_creds_psk_unload(creds);
g_free(creds->username);
}
qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
Error **errp)
{
+ g_autoptr(QCryptoTLSCredsBox) box = NULL;
g_autofree char *cacert = NULL;
g_autofree char *cacrl = NULL;
g_autofree char *cert = NULL;
trace_qcrypto_tls_creds_x509_load(creds, creds->parent_obj.dir);
+ if (creds->parent_obj.endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ box = qcrypto_tls_creds_box_new_server(GNUTLS_CRD_CERTIFICATE);
+ } else {
+ box = qcrypto_tls_creds_box_new_client(GNUTLS_CRD_CERTIFICATE);
+ }
+
+ ret = gnutls_certificate_allocate_credentials(&box->data.cert);
+ if (ret < 0) {
+ error_setg(errp, "Cannot allocate credentials: '%s'",
+ gnutls_strerror(ret));
+ return -1;
+ }
+
if (qcrypto_tls_creds_get_path(&creds->parent_obj,
QCRYPTO_TLS_CREDS_X509_CA_CERT,
true, &cacert, errp) < 0) {
return -1;
}
- ret = gnutls_certificate_allocate_credentials(&creds->data);
- if (ret < 0) {
- error_setg(errp, "Cannot allocate credentials: '%s'",
- gnutls_strerror(ret));
- return -1;
- }
-
- ret = gnutls_certificate_set_x509_trust_file(creds->data,
+ ret = gnutls_certificate_set_x509_trust_file(box->data.cert,
cacert,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
return -1;
}
}
- ret = gnutls_certificate_set_x509_key_file2(creds->data,
+ ret = gnutls_certificate_set_x509_key_file2(box->data.cert,
cert, key,
GNUTLS_X509_FMT_PEM,
password,
}
if (cacrl != NULL) {
- ret = gnutls_certificate_set_x509_crl_file(creds->data,
+ ret = gnutls_certificate_set_x509_crl_file(box->data.cert,
cacrl,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
if (isServer) {
if (qcrypto_tls_creds_get_dh_params_file(&creds->parent_obj, dhparams,
- &creds->parent_obj.dh_params,
+ &box->dh_params,
errp) < 0) {
return -1;
}
- gnutls_certificate_set_dh_params(creds->data,
- creds->parent_obj.dh_params);
+ gnutls_certificate_set_dh_params(box->data.cert, box->dh_params);
}
+ creds->parent_obj.box = g_steal_pointer(&box);
return 0;
}
-static void
-qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds)
-{
- if (creds->data) {
- gnutls_certificate_free_credentials(creds->data);
- creds->data = NULL;
- }
-}
-
-
#else /* ! CONFIG_GNUTLS */
}
-static void
-qcrypto_tls_creds_x509_unload(QCryptoTLSCredsX509 *creds G_GNUC_UNUSED)
-{
- /* nada */
-}
-
-
#endif /* ! CONFIG_GNUTLS */
{
QCryptoTLSCredsX509 *x509_creds = QCRYPTO_TLS_CREDS_X509(creds);
Error *local_err = NULL;
- gnutls_certificate_credentials_t creds_data = x509_creds->data;
- gnutls_dh_params_t creds_dh_params = creds->dh_params;
+ QCryptoTLSCredsBox *creds_box = creds->box;
- x509_creds->data = NULL;
- creds->dh_params = NULL;
+ creds->box = NULL;
qcrypto_tls_creds_x509_load(x509_creds, &local_err);
if (local_err) {
- qcrypto_tls_creds_x509_unload(x509_creds);
- if (creds->dh_params) {
- gnutls_dh_params_deinit(creds->dh_params);
- }
- x509_creds->data = creds_data;
- creds->dh_params = creds_dh_params;
+ creds->box = creds_box;
error_propagate(errp, local_err);
return false;
}
- if (creds_data) {
- gnutls_certificate_free_credentials(creds_data);
- }
- if (creds_dh_params) {
- gnutls_dh_params_deinit(creds_dh_params);
- }
+ qcrypto_tls_creds_box_unref(creds_box);
return true;
}
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
g_free(creds->passwordid);
- qcrypto_tls_creds_x509_unload(creds);
}
struct QCryptoTLSSession {
QCryptoTLSCreds *creds;
+ QCryptoTLSCredsBox *credsbox;
gnutls_session_t handle;
char *hostname;
char *authzid;
g_free(session->hostname);
g_free(session->peername);
g_free(session->authzid);
+ qcrypto_tls_creds_box_unref(session->credsbox);
object_unref(OBJECT(session->creds));
qemu_mutex_destroy(&session->lock);
g_free(session);
goto error;
}
- if (object_dynamic_cast(OBJECT(creds),
- TYPE_QCRYPTO_TLS_CREDS_ANON)) {
- QCryptoTLSCredsAnon *acreds = QCRYPTO_TLS_CREDS_ANON(creds);
- if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
- ret = gnutls_credentials_set(session->handle,
- GNUTLS_CRD_ANON,
- acreds->data.server);
- } else {
- ret = gnutls_credentials_set(session->handle,
- GNUTLS_CRD_ANON,
- acreds->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_PSK)) {
- QCryptoTLSCredsPSK *pcreds = QCRYPTO_TLS_CREDS_PSK(creds);
- 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);
+ ret = gnutls_credentials_set(session->handle,
+ creds->box->type,
+ creds->box->data.any);
+ if (ret < 0) {
+ error_setg(errp, "Cannot set session credentials: %s",
+ gnutls_strerror(ret));
+ goto error;
+ }
- ret = gnutls_credentials_set(session->handle,
- GNUTLS_CRD_CERTIFICATE,
- tcreds->data);
- if (ret < 0) {
- error_setg(errp, "Cannot set session credentials: %s",
- gnutls_strerror(ret));
- goto error;
- }
+ /*
+ * creds->box->data.any must be kept alive for as long
+ * as the gnutls_session_t is alive, so acquire a ref
+ */
+ qcrypto_tls_creds_box_ref(creds->box);
+ session->credsbox = creds->box;
- if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
- /* This requests, but does not enforce a client cert.
- * The cert checking code later does enforcement */
- gnutls_certificate_server_set_request(session->handle,
- GNUTLS_CERT_REQUEST);
- }
- } else {
- error_setg(errp, "Unsupported TLS credentials type %s",
- object_get_typename(OBJECT(creds)));
- goto error;
+ if (object_dynamic_cast(OBJECT(creds),
+ TYPE_QCRYPTO_TLS_CREDS_X509) &&
+ creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ /*
+ * This requests, but does not enforce a client cert.
+ * The cert checking code later does enforcement
+ */
+ gnutls_certificate_server_set_request(session->handle,
+ GNUTLS_CERT_REQUEST);
}
gnutls_transport_set_ptr(session->handle, session);