*
*/
+#include "qemu/osdep.h"
#include "crypto/tlscredsx509.h"
#include "crypto/tlscredspriv.h"
+#include "crypto/secret.h"
+#include "qapi/error.h"
#include "qom/object_interfaces.h"
#include "trace.h"
}
g_free(buffer);
+ buffer = NULL;
}
if (isServer) {
gsize buflen;
GError *gerr;
int ret = -1;
+ int err;
trace_qcrypto_tls_creds_x509_load_cert(creds, isServer, certFile);
- if (gnutls_x509_crt_init(&cert) < 0) {
- error_setg(errp, "Unable to initialize certificate");
+ err = gnutls_x509_crt_init(&cert);
+ if (err < 0) {
+ error_setg(errp, "Unable to initialize certificate: %s",
+ gnutls_strerror(err));
goto cleanup;
}
data.data = (unsigned char *)buf;
data.size = strlen(buf);
- if (gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM) < 0) {
+ err = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
error_setg(errp, isServer ?
- "Unable to import server certificate %s" :
- "Unable to import client certificate %s",
- certFile);
+ "Unable to import server certificate %s: %s" :
+ "Unable to import client certificate %s: %s",
+ certFile,
+ gnutls_strerror(err));
goto cleanup;
}
int ret = -1;
memset(cacerts, 0, sizeof(cacerts));
- if (access(certFile, R_OK) == 0) {
+ if (certFile &&
+ access(certFile, R_OK) == 0) {
cert = qcrypto_tls_creds_load_cert(creds,
certFile, isServer,
errp);
}
if (cert != NULL && key != NULL) {
+#if LIBGNUTLS_VERSION_NUMBER >= 0x030111
+ char *password = NULL;
+ if (creds->passwordid) {
+ password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
+ errp);
+ if (!password) {
+ goto cleanup;
+ }
+ }
+ ret = gnutls_certificate_set_x509_key_file2(creds->data,
+ cert, key,
+ GNUTLS_X509_FMT_PEM,
+ password,
+ 0);
+ g_free(password);
+#else /* LIBGNUTLS_VERSION_NUMBER < 0x030111 */
+ if (creds->passwordid) {
+ error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
+ goto cleanup;
+ }
ret = gnutls_certificate_set_x509_key_file(creds->data,
cert, key,
GNUTLS_X509_FMT_PEM);
+#endif
if (ret < 0) {
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
cert, key, gnutls_strerror(ret));
}
+static void
+qcrypto_tls_creds_x509_prop_set_passwordid(Object *obj,
+ const char *value,
+ Error **errp G_GNUC_UNUSED)
+{
+ QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
+
+ creds->passwordid = g_strdup(value);
+}
+
+
+static char *
+qcrypto_tls_creds_x509_prop_get_passwordid(Object *obj,
+ Error **errp G_GNUC_UNUSED)
+{
+ QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
+
+ return g_strdup(creds->passwordid);
+}
+
+
static bool
qcrypto_tls_creds_x509_prop_get_sanity(Object *obj,
Error **errp G_GNUC_UNUSED)
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
creds->sanityCheck = true;
-
- object_property_add_bool(obj, "loaded",
- qcrypto_tls_creds_x509_prop_get_loaded,
- qcrypto_tls_creds_x509_prop_set_loaded,
- NULL);
- object_property_add_bool(obj, "sanity-check",
- qcrypto_tls_creds_x509_prop_get_sanity,
- qcrypto_tls_creds_x509_prop_set_sanity,
- NULL);
}
{
QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
+ g_free(creds->passwordid);
qcrypto_tls_creds_x509_unload(creds);
}
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
ucc->complete = qcrypto_tls_creds_x509_complete;
+
+ object_class_property_add_bool(oc, "loaded",
+ qcrypto_tls_creds_x509_prop_get_loaded,
+ qcrypto_tls_creds_x509_prop_set_loaded,
+ NULL);
+ object_class_property_add_bool(oc, "sanity-check",
+ qcrypto_tls_creds_x509_prop_get_sanity,
+ qcrypto_tls_creds_x509_prop_set_sanity,
+ NULL);
+ object_class_property_add_str(oc, "passwordid",
+ qcrypto_tls_creds_x509_prop_get_passwordid,
+ qcrypto_tls_creds_x509_prop_set_passwordid,
+ NULL);
}