]> Git Repo - qemu.git/blobdiff - crypto/tlscredsx509.c
Merge remote-tracking branch 'remotes/rth/tags/pull-s390-20170613' into staging
[qemu.git] / crypto / tlscredsx509.c
index c5d1a0de30efbf6af7946aa2d125f858ce2c56a5..50eb54f6bbca4247596c256641f5687f7b4e9695 100644 (file)
  *
  */
 
+#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"
 
@@ -255,6 +258,7 @@ qcrypto_tls_creds_check_cert_key_purpose(QCryptoTLSCredsX509 *creds,
         }
 
         g_free(buffer);
+        buffer = NULL;
     }
 
     if (isServer) {
@@ -388,11 +392,14 @@ qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
     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;
     }
 
@@ -406,11 +413,13 @@ qcrypto_tls_creds_load_cert(QCryptoTLSCredsX509 *creds,
     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;
     }
 
@@ -485,7 +494,8 @@ qcrypto_tls_creds_x509_sanity_check(QCryptoTLSCredsX509 *creds,
     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);
@@ -605,9 +615,30 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
     }
 
     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));
@@ -735,6 +766,27 @@ qcrypto_tls_creds_x509_prop_set_sanity(Object *obj,
 }
 
 
+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)
@@ -758,15 +810,6 @@ qcrypto_tls_creds_x509_init(Object *obj)
     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);
 }
 
 
@@ -775,6 +818,7 @@ qcrypto_tls_creds_x509_finalize(Object *obj)
 {
     QCryptoTLSCredsX509 *creds = QCRYPTO_TLS_CREDS_X509(obj);
 
+    g_free(creds->passwordid);
     qcrypto_tls_creds_x509_unload(creds);
 }
 
@@ -785,6 +829,19 @@ qcrypto_tls_creds_x509_class_init(ObjectClass *oc, void *data)
     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);
 }
 
 
This page took 0.027546 seconds and 4 git commands to generate.