summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2021-06-16 11:01:40 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2021-06-16 11:01:40 +0000
commitf6fdc9b5f2a8f90937b36f2ebe55e98b9ee07139 (patch)
tree53bc28d420c50772174cfd0bbac3f1e2961c7e48
parent4d6dbe09049ee1a02fdb0aa3ae01c499dc033c27 (diff)
parent022ea47603de3465e4e80c0896af0485705d966a (diff)
downloadglib-f6fdc9b5f2a8f90937b36f2ebe55e98b9ee07139.tar.gz
Merge branch 'mcatanzaro/readable-private-key' into 'main'
gtlscertificate: make private key properties readable See merge request GNOME/glib!2087
-rw-r--r--gio/gtlscertificate.c68
-rw-r--r--gio/tests/gtesttlsbackend.c6
-rw-r--r--gio/tests/gtesttlsbackend.h3
-rw-r--r--gio/tests/tls-certificate.c67
4 files changed, 74 insertions, 70 deletions
diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c
index aadc562a6..cc4046c88 100644
--- a/gio/gtlscertificate.c
+++ b/gio/gtlscertificate.c
@@ -84,6 +84,8 @@ g_tls_certificate_get_property (GObject *object,
{
switch (prop_id)
{
+ case PROP_PRIVATE_KEY:
+ case PROP_PRIVATE_KEY_PEM:
case PROP_PKCS11_URI:
case PROP_PRIVATE_KEY_PKCS11_URI:
/* Subclasses must override this property but this allows older backends to not fatally error */
@@ -154,17 +156,25 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
- * GTlsCertificate:private-key:
+ * GTlsCertificate:private-key: (nullable)
*
* The DER (binary) encoded representation of the certificate's
- * private key, in either PKCS#1 format or unencrypted PKCS#8
- * format. This property (or the #GTlsCertificate:private-key-pem
- * property) can be set when constructing a key (eg, from a file),
- * but cannot be read.
+ * private key, in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017)
+ * or unencrypted [PKCS \#8 format.](https://datatracker.ietf.org/doc/html/rfc5208)
+ * PKCS \#8 format is supported since 2.32; earlier releases only
+ * support PKCS \#1. You can use the `openssl rsa` tool to convert
+ * PKCS \#8 keys to PKCS \#1.
*
- * PKCS#8 format is supported since 2.32; earlier releases only
- * support PKCS#1. You can use the `openssl rsa`
- * tool to convert PKCS#8 keys to PKCS#1.
+ * This property (or the #GTlsCertificate:private-key-pem property)
+ * can be set when constructing a key (for example, from a file).
+ * Since GLib 2.70, it is now also readable; however, be aware that if
+ * the private key is backed by a PKCS \#11 URI – for example, if it
+ * is stored on a smartcard – then this property will be %NULL. If so,
+ * the private key must be referenced via its PKCS \#11 URI,
+ * #GTlsCertificate:private-key-pkcs11-uri. You must check both
+ * properties to see if the certificate really has a private key.
+ * When this property is read, the output format will be unencrypted
+ * PKCS \#8.
*
* Since: 2.28
*/
@@ -173,22 +183,30 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
P_("Private key"),
P_("The DER representation of the certificate’s private key"),
G_TYPE_BYTE_ARRAY,
- G_PARAM_WRITABLE |
+ G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
- * GTlsCertificate:private-key-pem:
+ * GTlsCertificate:private-key-pem: (nullable)
*
* The PEM (ASCII) encoded representation of the certificate's
- * private key in either PKCS#1 format ("`BEGIN RSA PRIVATE
- * KEY`") or unencrypted PKCS#8 format ("`BEGIN
- * PRIVATE KEY`"). This property (or the
- * #GTlsCertificate:private-key property) can be set when
- * constructing a key (eg, from a file), but cannot be read.
+ * private key in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017)
+ * ("`BEGIN RSA PRIVATE KEY`") or unencrypted
+ * [PKCS \#8 format](https://datatracker.ietf.org/doc/html/rfc5208)
+ * ("`BEGIN PRIVATE KEY`"). PKCS \#8 format is supported since 2.32;
+ * earlier releases only support PKCS \#1. You can use the `openssl rsa`
+ * tool to convert PKCS \#8 keys to PKCS \#1.
*
- * PKCS#8 format is supported since 2.32; earlier releases only
- * support PKCS#1. You can use the `openssl rsa`
- * tool to convert PKCS#8 keys to PKCS#1.
+ * This property (or the #GTlsCertificate:private-key property)
+ * can be set when constructing a key (for example, from a file).
+ * Since GLib 2.70, it is now also readable; however, be aware that if
+ * the private key is backed by a PKCS \#11 URI - for example, if it
+ * is stored on a smartcard - then this property will be %NULL. If so,
+ * the private key must be referenced via its PKCS \#11 URI,
+ * #GTlsCertificate:private-key-pkcs11-uri. You must check both
+ * properties to see if the certificate really has a private key.
+ * When this property is read, the output format will be unencrypted
+ * PKCS \#8.
*
* Since: 2.28
*/
@@ -197,7 +215,7 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
P_("Private key (PEM)"),
P_("The PEM representation of the certificate’s private key"),
NULL,
- G_PARAM_WRITABLE |
+ G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
/**
@@ -222,10 +240,10 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
/**
* GTlsCertificate:pkcs11-uri: (nullable)
*
- * A URI referencing the PKCS \#11 objects containing an X.509 certificate
- * and optionally a private key.
+ * A URI referencing the [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html)
+ * objects containing an X.509 certificate and optionally a private key.
*
- * If %NULL the certificate is either not backed by PKCS \#11 or the
+ * If %NULL, the certificate is either not backed by PKCS \#11 or the
* #GTlsBackend does not support PKCS \#11.
*
* Since: 2.68
@@ -242,7 +260,8 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
/**
* GTlsCertificate:private-key-pkcs11-uri: (nullable)
*
- * A URI referencing a PKCS \#11 object containing a private key.
+ * A URI referencing a [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html)
+ * object containing a private key.
*
* Since: 2.68
*/
@@ -754,7 +773,8 @@ g_tls_certificate_new_from_files (const gchar *cert_file,
* @private_key_pkcs11_uri: (nullable): A PKCS \#11 URI
* @error: #GError for error reporting, or %NULL to ignore.
*
- * Creates a #GTlsCertificate from a PKCS \#11 URI.
+ * Creates a #GTlsCertificate from a
+ * [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html) URI.
*
* An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01`
*
diff --git a/gio/tests/gtesttlsbackend.c b/gio/tests/gtesttlsbackend.c
index 1e07c1e5e..6c48c2394 100644
--- a/gio/tests/gtesttlsbackend.c
+++ b/gio/tests/gtesttlsbackend.c
@@ -407,12 +407,6 @@ g_test_tls_connection_initable_iface_init (GInitableIface *iface)
iface->init = g_test_tls_connection_initable_init;
}
-const gchar *
-g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert)
-{
- return ((GTestTlsCertificate *)cert)->key_pem;
-}
-
/* Test database type */
typedef struct _GTestTlsDatabase GTestTlsDatabase;
diff --git a/gio/tests/gtesttlsbackend.h b/gio/tests/gtesttlsbackend.h
index 11a8bf149..07948fddc 100644
--- a/gio/tests/gtesttlsbackend.h
+++ b/gio/tests/gtesttlsbackend.h
@@ -39,9 +39,6 @@ struct _GTestTlsBackendClass {
GType _g_test_tls_backend_get_type (void);
-const gchar *g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert);
-
-
G_END_DECLS
#endif /* __G_TEST_TLS_BACKEND_H__ */
diff --git a/gio/tests/tls-certificate.c b/gio/tests/tls-certificate.c
index d0a908530..2995b1028 100644
--- a/gio/tests/tls-certificate.c
+++ b/gio/tests/tls-certificate.c
@@ -40,7 +40,7 @@ pem_parser (const Reference *ref)
gchar *pem;
gsize pem_len = 0;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
/* Check PEM parsing in certificate, private key order. */
@@ -55,13 +55,12 @@ pem_parser (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_object_unref (cert);
@@ -89,13 +88,12 @@ pem_parser (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_free (pem);
g_object_unref (cert);
@@ -111,11 +109,10 @@ pem_parser (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_null (parsed_key_pem);
g_free (pem);
@@ -141,7 +138,7 @@ pem_parser_handles_chain (const Reference *ref)
GTlsCertificate *original_cert;
gchar *pem;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
/* Check that a chain with exactly three certificates is returned */
@@ -156,14 +153,14 @@ pem_parser_handles_chain (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_clear_pointer (&parsed_cert_pem, g_free);
/* Make sure the private key was parsed */
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
/* Now test the second cert */
issuer = g_tls_certificate_get_issuer (cert);
@@ -175,12 +172,12 @@ pem_parser_handles_chain (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[1]);
g_clear_pointer (&parsed_cert_pem, g_free);
/* Only the first cert should have a private key */
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_null (parsed_key_pem);
/* Now test the final cert */
@@ -190,11 +187,11 @@ pem_parser_handles_chain (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[2]);
g_clear_pointer (&parsed_cert_pem, g_free);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_null (parsed_key_pem);
g_object_unref (original_cert);
@@ -237,7 +234,7 @@ from_file (const Reference *ref)
{
GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
cert = g_tls_certificate_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", NULL),
@@ -247,13 +244,12 @@ from_file (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_object_unref (cert);
}
@@ -263,7 +259,7 @@ from_files (const Reference *ref)
{
GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
@@ -274,13 +270,12 @@ from_files (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_object_unref (cert);
@@ -332,7 +327,7 @@ from_files_crlf (const Reference *ref)
{
GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-crlf.pem", NULL),
@@ -343,13 +338,12 @@ from_files_crlf (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_crlf_pem);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key_crlf_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_object_unref (cert);
}
@@ -359,7 +353,7 @@ from_files_pkcs8 (const Reference *ref)
{
GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL;
- const gchar *parsed_key_pem = NULL;
+ gchar *parsed_key_pem = NULL;
GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", NULL),
@@ -370,13 +364,12 @@ from_files_pkcs8 (const Reference *ref)
g_object_get (cert,
"certificate-pem", &parsed_cert_pem,
+ "private-key-pem", &parsed_key_pem,
NULL);
- parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
- g_free (parsed_cert_pem);
- parsed_cert_pem = NULL;
+ g_clear_pointer (&parsed_cert_pem, g_free);
g_assert_cmpstr (parsed_key_pem, ==, ref->key8_pem);
- parsed_key_pem = NULL;
+ g_clear_pointer (&parsed_key_pem, g_free);
g_object_unref (cert);
}