mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 22:46:15 +01:00
gtlscertificate: Add support for PKCS #11 backed certificates
This reverts commit d58e5de9e9
.
This commit is contained in:
parent
42961e819d
commit
f9fc29f0b7
@ -3705,6 +3705,7 @@ GTlsCertificate
|
|||||||
g_tls_certificate_new_from_pem
|
g_tls_certificate_new_from_pem
|
||||||
g_tls_certificate_new_from_file
|
g_tls_certificate_new_from_file
|
||||||
g_tls_certificate_new_from_files
|
g_tls_certificate_new_from_files
|
||||||
|
g_tls_certificate_new_from_pkcs11_uris
|
||||||
g_tls_certificate_list_new_from_file
|
g_tls_certificate_list_new_from_file
|
||||||
g_tls_certificate_get_issuer
|
g_tls_certificate_get_issuer
|
||||||
g_tls_certificate_verify
|
g_tls_certificate_verify
|
||||||
|
@ -60,7 +60,9 @@ enum
|
|||||||
PROP_CERTIFICATE_PEM,
|
PROP_CERTIFICATE_PEM,
|
||||||
PROP_PRIVATE_KEY,
|
PROP_PRIVATE_KEY,
|
||||||
PROP_PRIVATE_KEY_PEM,
|
PROP_PRIVATE_KEY_PEM,
|
||||||
PROP_ISSUER
|
PROP_ISSUER,
|
||||||
|
PROP_PKCS11_URI,
|
||||||
|
PROP_PRIVATE_KEY_PKCS11_URI,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -74,7 +76,16 @@ g_tls_certificate_get_property (GObject *object,
|
|||||||
GValue *value,
|
GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PKCS11_URI:
|
||||||
|
case PROP_PRIVATE_KEY_PKCS11_URI:
|
||||||
|
/* Subclasses must override this property but this allows older backends to not fatally error */
|
||||||
|
g_value_set_static_string (value, NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -83,7 +94,15 @@ g_tls_certificate_set_property (GObject *object,
|
|||||||
const GValue *value,
|
const GValue *value,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PKCS11_URI:
|
||||||
|
case PROP_PRIVATE_KEY_PKCS11_URI:
|
||||||
|
/* Subclasses must override this property but this allows older backends to not fatally error */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -193,6 +212,42 @@ g_tls_certificate_class_init (GTlsCertificateClass *class)
|
|||||||
G_PARAM_READWRITE |
|
G_PARAM_READWRITE |
|
||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTlsCertificate:pkcs11-uri: (nullable)
|
||||||
|
*
|
||||||
|
* A URI referencing the PKCS \#11 objects containing an X.509 certificate
|
||||||
|
* and optionally a private key.
|
||||||
|
*
|
||||||
|
* If %NULL the certificate is either not backed by PKCS \#11 or the
|
||||||
|
* #GTlsBackend does not support PKCS \#11.
|
||||||
|
*
|
||||||
|
* Since: 2.68
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PKCS11_URI,
|
||||||
|
g_param_spec_string ("pkcs11-uri",
|
||||||
|
P_("PKCS #11 URI"),
|
||||||
|
P_("The PKCS #11 URI"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTlsCertificate:private-key-pkcs11-uri: (nullable)
|
||||||
|
*
|
||||||
|
* A URI referencing a PKCS \#11 object containing a private key.
|
||||||
|
*
|
||||||
|
* Since: 2.68
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY_PKCS11_URI,
|
||||||
|
g_param_spec_string ("private-key-pkcs11-uri",
|
||||||
|
P_("PKCS #11 URI"),
|
||||||
|
P_("The PKCS #11 URI for a private key"),
|
||||||
|
NULL,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GTlsCertificate *
|
static GTlsCertificate *
|
||||||
@ -591,6 +646,77 @@ g_tls_certificate_new_from_files (const gchar *cert_file,
|
|||||||
return cert;
|
return cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_tls_certificate_new_from_pkcs11_uris:
|
||||||
|
* @pkcs11_uri: A PKCS \#11 URI
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* An example @pkcs11_uri would be `pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01`
|
||||||
|
*
|
||||||
|
* Where the token’s layout is:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* Object 0:
|
||||||
|
* URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=private%20key;type=private
|
||||||
|
* Type: Private key (RSA-2048)
|
||||||
|
* ID: 01
|
||||||
|
*
|
||||||
|
* Object 1:
|
||||||
|
* URL: pkcs11:model=Model;manufacturer=Manufacture;serial=1;token=My%20Client%20Certificate;id=%01;object=Certificate%20for%20Authentication;type=cert
|
||||||
|
* Type: X.509 Certificate (RSA-2048)
|
||||||
|
* ID: 01
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In this case the certificate and private key would both be detected and used as expected.
|
||||||
|
* @pkcs_uri may also just reference an X.509 certificate object and then optionally
|
||||||
|
* @private_key_pkcs11_uri allows using a private key exposed under a different URI.
|
||||||
|
*
|
||||||
|
* Note that the private key is not accessed until usage and may fail or require a PIN later.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the new certificate, or %NULL on error
|
||||||
|
*
|
||||||
|
* Since: 2.68
|
||||||
|
*/
|
||||||
|
GTlsCertificate *
|
||||||
|
g_tls_certificate_new_from_pkcs11_uris (const gchar *pkcs11_uri,
|
||||||
|
const gchar *private_key_pkcs11_uri,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GObject *cert;
|
||||||
|
GTlsBackend *backend;
|
||||||
|
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
g_return_val_if_fail (pkcs11_uri, NULL);
|
||||||
|
|
||||||
|
backend = g_tls_backend_get_default ();
|
||||||
|
|
||||||
|
cert = g_initable_new (g_tls_backend_get_certificate_type (backend),
|
||||||
|
NULL, error,
|
||||||
|
"pkcs11-uri", pkcs11_uri,
|
||||||
|
"private-key-pkcs11-uri", private_key_pkcs11_uri,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (cert != NULL)
|
||||||
|
{
|
||||||
|
gchar *objects_uri;
|
||||||
|
|
||||||
|
/* Old implementations might not override this property */
|
||||||
|
g_object_get (cert, "pkcs11-uri", &objects_uri, NULL);
|
||||||
|
if (objects_uri == NULL)
|
||||||
|
{
|
||||||
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This GTlsBackend does not support creating PKCS #11 certificates"));
|
||||||
|
g_object_unref (cert);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_free (objects_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return G_TLS_CERTIFICATE (cert);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_tls_certificate_list_new_from_file:
|
* g_tls_certificate_list_new_from_file:
|
||||||
* @file: (type filename): file containing PEM-encoded certificates to import
|
* @file: (type filename): file containing PEM-encoded certificates to import
|
||||||
|
@ -71,6 +71,11 @@ GLIB_AVAILABLE_IN_ALL
|
|||||||
GTlsCertificate *g_tls_certificate_new_from_files (const gchar *cert_file,
|
GTlsCertificate *g_tls_certificate_new_from_files (const gchar *cert_file,
|
||||||
const gchar *key_file,
|
const gchar *key_file,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
GLIB_AVAILABLE_IN_2_68
|
||||||
|
GTlsCertificate *g_tls_certificate_new_from_pkcs11_uris (const gchar *pkcs11_uri,
|
||||||
|
const gchar *private_key_pkcs11_uri,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
GLIB_AVAILABLE_IN_ALL
|
GLIB_AVAILABLE_IN_ALL
|
||||||
GList *g_tls_certificate_list_new_from_file (const gchar *file,
|
GList *g_tls_certificate_list_new_from_file (const gchar *file,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
@ -93,6 +93,8 @@ struct _GTestTlsCertificate {
|
|||||||
gchar *key_pem;
|
gchar *key_pem;
|
||||||
gchar *cert_pem;
|
gchar *cert_pem;
|
||||||
GTlsCertificate *issuer;
|
GTlsCertificate *issuer;
|
||||||
|
gchar *pkcs11_uri;
|
||||||
|
gchar *private_key_pkcs11_uri;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GTestTlsCertificateClass {
|
struct _GTestTlsCertificateClass {
|
||||||
@ -105,7 +107,9 @@ enum
|
|||||||
PROP_CERT_CERTIFICATE_PEM,
|
PROP_CERT_CERTIFICATE_PEM,
|
||||||
PROP_CERT_PRIVATE_KEY,
|
PROP_CERT_PRIVATE_KEY,
|
||||||
PROP_CERT_PRIVATE_KEY_PEM,
|
PROP_CERT_PRIVATE_KEY_PEM,
|
||||||
PROP_CERT_ISSUER
|
PROP_CERT_ISSUER,
|
||||||
|
PROP_CERT_PKCS11_URI,
|
||||||
|
PROP_CERT_PRIVATE_KEY_PKCS11_URI,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void g_test_tls_certificate_initable_iface_init (GInitableIface *iface);
|
static void g_test_tls_certificate_initable_iface_init (GInitableIface *iface);
|
||||||
@ -143,6 +147,15 @@ g_test_tls_certificate_get_property (GObject *object,
|
|||||||
case PROP_CERT_ISSUER:
|
case PROP_CERT_ISSUER:
|
||||||
g_value_set_object (value, cert->issuer);
|
g_value_set_object (value, cert->issuer);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CERT_PKCS11_URI:
|
||||||
|
/* This test value simulates a backend that ignores the value
|
||||||
|
because it is unsupported */
|
||||||
|
if (g_strcmp0 (cert->pkcs11_uri, "unsupported") != 0)
|
||||||
|
g_value_set_string (value, cert->pkcs11_uri);
|
||||||
|
break;
|
||||||
|
case PROP_CERT_PRIVATE_KEY_PKCS11_URI:
|
||||||
|
g_value_set_string (value, cert->private_key_pkcs11_uri);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
break;
|
break;
|
||||||
@ -168,6 +181,12 @@ g_test_tls_certificate_set_property (GObject *object,
|
|||||||
case PROP_CERT_ISSUER:
|
case PROP_CERT_ISSUER:
|
||||||
cert->issuer = g_value_dup_object (value);
|
cert->issuer = g_value_dup_object (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CERT_PKCS11_URI:
|
||||||
|
cert->pkcs11_uri = g_value_dup_string (value);
|
||||||
|
break;
|
||||||
|
case PROP_CERT_PRIVATE_KEY_PKCS11_URI:
|
||||||
|
cert->private_key_pkcs11_uri = g_value_dup_string (value);
|
||||||
|
break;
|
||||||
case PROP_CERT_CERTIFICATE:
|
case PROP_CERT_CERTIFICATE:
|
||||||
case PROP_CERT_PRIVATE_KEY:
|
case PROP_CERT_PRIVATE_KEY:
|
||||||
/* ignore */
|
/* ignore */
|
||||||
@ -185,6 +204,8 @@ g_test_tls_certificate_finalize (GObject *object)
|
|||||||
|
|
||||||
g_free (cert->cert_pem);
|
g_free (cert->cert_pem);
|
||||||
g_free (cert->key_pem);
|
g_free (cert->key_pem);
|
||||||
|
g_free (cert->pkcs11_uri);
|
||||||
|
g_free (cert->private_key_pkcs11_uri);
|
||||||
g_clear_object (&cert->issuer);
|
g_clear_object (&cert->issuer);
|
||||||
|
|
||||||
G_OBJECT_CLASS (g_test_tls_certificate_parent_class)->finalize (object);
|
G_OBJECT_CLASS (g_test_tls_certificate_parent_class)->finalize (object);
|
||||||
@ -207,6 +228,8 @@ g_test_tls_certificate_class_init (GTestTlsCertificateClass *test_class)
|
|||||||
g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY, "private-key");
|
g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY, "private-key");
|
||||||
g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PEM, "private-key-pem");
|
g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PEM, "private-key-pem");
|
||||||
g_object_class_override_property (gobject_class, PROP_CERT_ISSUER, "issuer");
|
g_object_class_override_property (gobject_class, PROP_CERT_ISSUER, "issuer");
|
||||||
|
g_object_class_override_property (gobject_class, PROP_CERT_PKCS11_URI, "pkcs11-uri");
|
||||||
|
g_object_class_override_property (gobject_class, PROP_CERT_PRIVATE_KEY_PKCS11_URI, "private-key-pkcs11-uri");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -398,6 +398,38 @@ list_from_file (const Reference *ref)
|
|||||||
g_assert_cmpint (g_list_length (list), ==, 0);
|
g_assert_cmpint (g_list_length (list), ==, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
from_pkcs11_uri (void)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GTlsCertificate *cert;
|
||||||
|
gchar *pkcs11_uri = NULL;
|
||||||
|
|
||||||
|
cert = g_tls_certificate_new_from_pkcs11_uris ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_nonnull (cert);
|
||||||
|
|
||||||
|
g_object_get (cert, "pkcs11-uri", &pkcs11_uri, NULL);
|
||||||
|
g_assert_cmpstr ("pkcs11:model=p11-kit-trust;manufacturer=PKCS%2311%20Kit;serial=1;token=ca-bundle.crt", ==, pkcs11_uri);
|
||||||
|
g_free (pkcs11_uri);
|
||||||
|
|
||||||
|
g_object_unref (cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
from_unsupported_pkcs11_uri (void)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
GTlsCertificate *cert;
|
||||||
|
|
||||||
|
/* This is a magic value in gtesttlsbackend.c simulating an unsupported backend */
|
||||||
|
cert = g_tls_certificate_new_from_pkcs11_uris ("unsupported", NULL, &error);
|
||||||
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
|
||||||
|
g_assert_null (cert);
|
||||||
|
|
||||||
|
g_clear_error (&error);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
@ -464,6 +496,10 @@ main (int argc,
|
|||||||
&ref, (GTestDataFunc)from_files_pkcs8enc);
|
&ref, (GTestDataFunc)from_files_pkcs8enc);
|
||||||
g_test_add_data_func ("/tls-certificate/list_from_file",
|
g_test_add_data_func ("/tls-certificate/list_from_file",
|
||||||
&ref, (GTestDataFunc)list_from_file);
|
&ref, (GTestDataFunc)list_from_file);
|
||||||
|
g_test_add_func ("/tls-certificate/pkcs11-uri",
|
||||||
|
from_pkcs11_uri);
|
||||||
|
g_test_add_func ("/tls-certificate/pkcs11-uri-unsupported",
|
||||||
|
from_unsupported_pkcs11_uri);
|
||||||
|
|
||||||
rtv = g_test_run();
|
rtv = g_test_run();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user