[glib-networking/pgriffis/gtlscertificate-password: 5/5] openssl: Add PKCS #12 support
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/pgriffis/gtlscertificate-password: 5/5] openssl: Add PKCS #12 support
- Date: Thu, 2 Sep 2021 19:37:09 +0000 (UTC)
commit af79107eff6e6e47a3caf6485a721017d8f97073
Author: Patrick Griffis <pgriffis igalia com>
Date: Thu Sep 2 14:36:46 2021 -0500
openssl: Add PKCS #12 support
tls/openssl/gtlscertificate-openssl.c | 105 ++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
---
diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c
index 01ed1773..9df06274 100644
--- a/tls/openssl/gtlscertificate-openssl.c
+++ b/tls/openssl/gtlscertificate-openssl.c
@@ -27,6 +27,7 @@
#include <string.h>
#include "openssl-include.h"
+#include <openssl/pkcs12.h>
#include "gtlscertificate-openssl.h"
#include <glib/gi18n-lib.h>
@@ -38,9 +39,13 @@ struct _GTlsCertificateOpenssl
X509 *cert;
EVP_PKEY *key;
+ GBytes *pkcs12_bytes;
+ char *password;
+
GTlsCertificateOpenssl *issuer;
GError *construct_error;
+ gboolean construct_needs_pkcs12_password;
guint have_cert : 1;
guint have_key : 1;
@@ -61,6 +66,8 @@ enum
PROP_ISSUER_NAME,
PROP_DNS_NAMES,
PROP_IP_ADDRESSES,
+ PROP_PKCS12_BYTES,
+ PROP_PASSWORD,
};
static void g_tls_certificate_openssl_initable_iface_init (GInitableIface *iface);
@@ -205,6 +212,78 @@ out:
return result;
}
+static void
+maybe_import_pkcs12 (GTlsCertificateOpenssl *openssl)
+{
+ PKCS12 *p12 = NULL;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca = NULL;
+ EVP_PKEY *key = NULL;
+ BIO *bio = NULL;
+ gsize bytes_size;
+ const guint8 *bytes;
+ int status;
+ char error_buffer[256] = { 0 };
+
+ /* If password is set first. */
+ if (!openssl->pkcs12_bytes)
+ return;
+
+ bytes = g_bytes_get_data (openssl->pkcs12_bytes, &bytes_size);
+
+ bio = BIO_new (BIO_s_mem ());
+ status = BIO_write (bio, bytes, bytes_size);
+ if (status <= 0)
+ goto import_failed;
+ g_assert (status == bytes_size);
+
+ p12 = d2i_PKCS12_bio (bio, NULL);
+ if (p12 == NULL)
+ goto import_failed;
+
+ status = PKCS12_parse (p12, openssl->password, &key, &cert, &ca);
+ g_clear_pointer (&bio, BIO_free_all);
+
+ if (status != 1)
+ {
+ if (ERR_GET_REASON (ERR_peek_last_error ()) == PKCS12_R_MAC_VERIFY_FAILURE)
+ openssl->construct_needs_pkcs12_password = TRUE;
+ goto import_failed;
+ }
+
+ /* Clear previous failure now that we have the password. */
+ if (openssl->construct_needs_pkcs12_password)
+ g_clear_error (&openssl->construct_error);
+
+ // TODO: Handle chain
+ if (cert)
+ {
+ openssl->cert = g_steal_pointer (&cert);
+ openssl->have_cert = TRUE;
+ }
+
+ if (key)
+ {
+ openssl->key = g_steal_pointer (&key);
+ openssl->have_key = TRUE;
+ }
+
+ g_clear_pointer (&p12, PKCS12_free);
+ return;
+
+import_failed:
+ g_clear_error (&openssl->construct_error);
+
+ if (!error_buffer[0])
+ ERR_error_string_n (ERR_get_error (), error_buffer, sizeof (error_buffer));
+
+ g_set_error (&openssl->construct_error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("Failed to import PKCS #12: %s"), error_buffer);
+
+ g_clear_pointer (&p12, PKCS12_free);
+ g_clear_pointer (&bio, BIO_free_all);
+}
+
static void
g_tls_certificate_openssl_get_property (GObject *object,
guint prop_id,
@@ -228,6 +307,10 @@ g_tls_certificate_openssl_get_property (GObject *object,
switch (prop_id)
{
+ case PROP_PKCS12_BYTES:
+ g_value_set_boxed (value, openssl->pkcs12_bytes);
+ break;
+
case PROP_CERTIFICATE:
/* NOTE: we do the two calls to avoid openssl allocating the buffer for us */
size = i2d_X509 (openssl->cert, NULL);
@@ -344,6 +427,26 @@ g_tls_certificate_openssl_set_property (GObject *object,
switch (prop_id)
{
+ case PROP_PASSWORD:
+ openssl->password = g_value_dup_string (value);
+ if (openssl->password)
+ {
+ g_return_if_fail (openssl->have_cert == FALSE);
+ g_return_if_fail (openssl->have_key == FALSE);
+ maybe_import_pkcs12 (openssl);
+ }
+ break;
+
+ case PROP_PKCS12_BYTES:
+ openssl->pkcs12_bytes = g_value_dup_boxed (value);
+ if (openssl->pkcs12_bytes)
+ {
+ g_return_if_fail (openssl->have_cert == FALSE);
+ g_return_if_fail (openssl->have_key == FALSE);
+ maybe_import_pkcs12 (openssl);
+ }
+ break;
+
case PROP_CERTIFICATE:
bytes = g_value_get_boxed (value);
if (!bytes)
@@ -556,6 +659,8 @@ g_tls_certificate_openssl_class_init (GTlsCertificateOpensslClass *klass)
g_object_class_override_property (gobject_class, PROP_ISSUER_NAME, "issuer-name");
g_object_class_override_property (gobject_class, PROP_DNS_NAMES, "dns-names");
g_object_class_override_property (gobject_class, PROP_IP_ADDRESSES, "ip-addresses");
+ g_object_class_override_property (gobject_class, PROP_PKCS12_BYTES, "pkcs12-bytes");
+ g_object_class_override_property (gobject_class, PROP_PASSWORD, "password");
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]