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
commit f6fdc9b5f2
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)
{
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 certificates 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 certificates 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`
*

View File

@ -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;

View File

@ -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__ */

View File

@ -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);
}