Merge branch 'mcatanzaro/readable-private-key' into 'main'

gtlscertificate: make private key properties readable

See merge request GNOME/glib!2087
This commit is contained in:
Philip Withnall
2021-06-16 11:01:40 +00:00
4 changed files with 74 additions and 70 deletions

View File

@@ -84,6 +84,8 @@ g_tls_certificate_get_property (GObject *object,
{ {
switch (prop_id) switch (prop_id)
{ {
case PROP_PRIVATE_KEY:
case PROP_PRIVATE_KEY_PEM:
case PROP_PKCS11_URI: case PROP_PKCS11_URI:
case PROP_PRIVATE_KEY_PKCS11_URI: case PROP_PRIVATE_KEY_PKCS11_URI:
/* Subclasses must override this property but this allows older backends to not fatally error */ /* 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_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
/** /**
* GTlsCertificate:private-key: * GTlsCertificate:private-key: (nullable)
* *
* The DER (binary) encoded representation of the certificate's * The DER (binary) encoded representation of the certificate's
* private key, in either PKCS#1 format or unencrypted PKCS#8 * private key, in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017)
* format. This property (or the #GTlsCertificate:private-key-pem * or unencrypted [PKCS \#8 format.](https://datatracker.ietf.org/doc/html/rfc5208)
* property) can be set when constructing a key (eg, from a file), * PKCS \#8 format is supported since 2.32; earlier releases only
* but cannot be read. * 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 * This property (or the #GTlsCertificate:private-key-pem property)
* support PKCS#1. You can use the `openssl rsa` * can be set when constructing a key (for example, from a file).
* tool to convert PKCS#8 keys to PKCS#1. * 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 * Since: 2.28
*/ */
@@ -173,22 +183,30 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
P_("Private key"), P_("Private key"),
P_("The DER representation of the certificates private key"), P_("The DER representation of the certificates private key"),
G_TYPE_BYTE_ARRAY, G_TYPE_BYTE_ARRAY,
G_PARAM_WRITABLE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
/** /**
* GTlsCertificate:private-key-pem: * GTlsCertificate:private-key-pem: (nullable)
* *
* The PEM (ASCII) encoded representation of the certificate's * The PEM (ASCII) encoded representation of the certificate's
* private key in either PKCS#1 format ("`BEGIN RSA PRIVATE * private key in either [PKCS \#1 format](https://datatracker.ietf.org/doc/html/rfc8017)
* KEY`") or unencrypted PKCS#8 format ("`BEGIN * ("`BEGIN RSA PRIVATE KEY`") or unencrypted
* PRIVATE KEY`"). This property (or the * [PKCS \#8 format](https://datatracker.ietf.org/doc/html/rfc5208)
* #GTlsCertificate:private-key property) can be set when * ("`BEGIN PRIVATE KEY`"). PKCS \#8 format is supported since 2.32;
* constructing a key (eg, from a file), but cannot be read. * 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 * This property (or the #GTlsCertificate:private-key property)
* support PKCS#1. You can use the `openssl rsa` * can be set when constructing a key (for example, from a file).
* tool to convert PKCS#8 keys to PKCS#1. * 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 * Since: 2.28
*/ */
@@ -197,7 +215,7 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
P_("Private key (PEM)"), P_("Private key (PEM)"),
P_("The PEM representation of the certificates private key"), P_("The PEM representation of the certificates private key"),
NULL, NULL,
G_PARAM_WRITABLE | G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); G_PARAM_STATIC_STRINGS));
/** /**
@@ -222,10 +240,10 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
/** /**
* GTlsCertificate:pkcs11-uri: (nullable) * GTlsCertificate:pkcs11-uri: (nullable)
* *
* A URI referencing the PKCS \#11 objects containing an X.509 certificate * A URI referencing the [PKCS \#11](https://docs.oasis-open.org/pkcs11/pkcs11-base/v3.0/os/pkcs11-base-v3.0-os.html)
* and optionally a private key. * 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. * #GTlsBackend does not support PKCS \#11.
* *
* Since: 2.68 * Since: 2.68
@@ -242,7 +260,8 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
/** /**
* GTlsCertificate:private-key-pkcs11-uri: (nullable) * 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 * 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 * @private_key_pkcs11_uri: (nullable): A PKCS \#11 URI
* @error: #GError for error reporting, or %NULL to ignore. * @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` * An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01`
* *

View File

@@ -407,12 +407,6 @@ g_test_tls_connection_initable_iface_init (GInitableIface *iface)
iface->init = g_test_tls_connection_initable_init; 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 */ /* Test database type */
typedef struct _GTestTlsDatabase GTestTlsDatabase; typedef struct _GTestTlsDatabase GTestTlsDatabase;

View File

@@ -39,9 +39,6 @@ struct _GTestTlsBackendClass {
GType _g_test_tls_backend_get_type (void); GType _g_test_tls_backend_get_type (void);
const gchar *g_test_tls_connection_get_private_key_pem (GTlsCertificate *cert);
G_END_DECLS G_END_DECLS
#endif /* __G_TEST_TLS_BACKEND_H__ */ #endif /* __G_TEST_TLS_BACKEND_H__ */

View File

@@ -40,7 +40,7 @@ pem_parser (const Reference *ref)
gchar *pem; gchar *pem;
gsize pem_len = 0; gsize pem_len = 0;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
/* Check PEM parsing in certificate, private key order. */ /* Check PEM parsing in certificate, private key order. */
@@ -55,13 +55,12 @@ pem_parser (const Reference *ref)
g_object_get (cert, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); 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); g_object_unref (cert);
@@ -89,13 +88,12 @@ pem_parser (const Reference *ref)
g_object_get (cert, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); 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_free (pem);
g_object_unref (cert); g_object_unref (cert);
@@ -111,11 +109,10 @@ pem_parser (const Reference *ref)
g_object_get (cert, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_null (parsed_key_pem); g_assert_null (parsed_key_pem);
g_free (pem); g_free (pem);
@@ -141,7 +138,7 @@ pem_parser_handles_chain (const Reference *ref)
GTlsCertificate *original_cert; GTlsCertificate *original_cert;
gchar *pem; gchar *pem;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
/* Check that a chain with exactly three certificates is returned */ /* 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, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_clear_pointer (&parsed_cert_pem, g_free); g_clear_pointer (&parsed_cert_pem, g_free);
/* Make sure the private key was parsed */ /* 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); 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 */ /* Now test the second cert */
issuer = g_tls_certificate_get_issuer (cert); issuer = g_tls_certificate_get_issuer (cert);
@@ -175,12 +172,12 @@ pem_parser_handles_chain (const Reference *ref)
g_object_get (cert, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[1]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[1]);
g_clear_pointer (&parsed_cert_pem, g_free); g_clear_pointer (&parsed_cert_pem, g_free);
/* Only the first cert should have a private key */ /* 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); g_assert_null (parsed_key_pem);
/* Now test the final cert */ /* Now test the final cert */
@@ -190,11 +187,11 @@ pem_parser_handles_chain (const Reference *ref)
g_object_get (cert, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[2]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[2]);
g_clear_pointer (&parsed_cert_pem, g_free); 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_assert_null (parsed_key_pem);
g_object_unref (original_cert); g_object_unref (original_cert);
@@ -237,7 +234,7 @@ from_file (const Reference *ref)
{ {
GTlsCertificate *cert; GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
cert = g_tls_certificate_new_from_file (g_test_get_filename (G_TEST_DIST, "cert-tests", "key-cert.pem", 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, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); 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); g_object_unref (cert);
} }
@@ -263,7 +259,7 @@ from_files (const Reference *ref)
{ {
GTlsCertificate *cert; GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", 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, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key_pem); 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); g_object_unref (cert);
@@ -332,7 +327,7 @@ from_files_crlf (const Reference *ref)
{ {
GTlsCertificate *cert; GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert-crlf.pem", 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, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_crlf_pem); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_crlf_pem);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key_crlf_pem); 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); g_object_unref (cert);
} }
@@ -359,7 +353,7 @@ from_files_pkcs8 (const Reference *ref)
{ {
GTlsCertificate *cert; GTlsCertificate *cert;
gchar *parsed_cert_pem = NULL; gchar *parsed_cert_pem = NULL;
const gchar *parsed_key_pem = NULL; gchar *parsed_key_pem = NULL;
GError *error = NULL; GError *error = NULL;
cert = g_tls_certificate_new_from_files (g_test_get_filename (G_TEST_DIST, "cert-tests", "cert1.pem", 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, g_object_get (cert,
"certificate-pem", &parsed_cert_pem, "certificate-pem", &parsed_cert_pem,
"private-key-pem", &parsed_key_pem,
NULL); NULL);
parsed_key_pem = g_test_tls_connection_get_private_key_pem (cert);
g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]); g_assert_cmpstr (parsed_cert_pem, ==, ref->cert_pems[0]);
g_free (parsed_cert_pem); g_clear_pointer (&parsed_cert_pem, g_free);
parsed_cert_pem = NULL;
g_assert_cmpstr (parsed_key_pem, ==, ref->key8_pem); 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); g_object_unref (cert);
} }