|
Packit |
b00eeb |
/*
|
|
Packit |
b00eeb |
* Copyright (C) 2011 Collabora Ltd.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
b00eeb |
* it under the terms of the GNU Lesser General Public License as
|
|
Packit |
b00eeb |
* published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
b00eeb |
* the License, or (at your option) any later version.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
b00eeb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b00eeb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
b00eeb |
* Lesser General Public License for more details.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
b00eeb |
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Author: Stef Walter <stefw@collabora.co.uk>
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "config.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr-certificate-request.h"
|
|
Packit |
b00eeb |
#include "gcr-key-mechanisms.h"
|
|
Packit |
b00eeb |
#include "gcr-subject-public-key.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include "gcr/gcr-enum-types-base.h"
|
|
Packit |
b00eeb |
#include "gcr/gcr-oids.h"
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <egg/egg-armor.h>
|
|
Packit |
b00eeb |
#include <egg/egg-asn1x.h>
|
|
Packit |
b00eeb |
#include <egg/egg-asn1-defs.h>
|
|
Packit |
b00eeb |
#include <egg/egg-dn.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#include <glib/gi18n-lib.h>
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* SECTION:gcr-certificate-request
|
|
Packit |
b00eeb |
* @title: GcrCertificateRequest
|
|
Packit |
b00eeb |
* @short_description: Represents a certificate request
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This is an object that allows creation of certificate requests. A
|
|
Packit |
b00eeb |
* certificate request is sent to a certificate authority to request an
|
|
Packit |
b00eeb |
* X.509 certificate.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Use gcr_certificate_request_prepare() to create a blank certificate
|
|
Packit |
b00eeb |
* request for a given private key. Set the common name on the certificate
|
|
Packit |
b00eeb |
* request with gcr_certificate_request_set_cn(), and then sign the request
|
|
Packit |
b00eeb |
* with gcr_certificate_request_complete_async().
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrCertificateRequest:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Represents a certificate request.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrCertificateRequestFormat:
|
|
Packit |
b00eeb |
* @GCR_CERTIFICATE_REQUEST_PKCS10: certificate request is in PKCS\#10 format
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The format of a certificate request. Currently only PKCS\#10 is supported.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
#define GCR_CERTIFICATE_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCR_TYPE_CERTIFICATE_REQUEST, GcrCertificateRequestClass))
|
|
Packit |
b00eeb |
#define GCR_IS_CERTIFICATE_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCR_TYPE_CERTIFICATE_REQUEST))
|
|
Packit |
b00eeb |
#define GCR_CERTIFICATE_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GCR_TYPE_CERTIFICATE_REQUEST, GcrCertificateRequestClass))
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct _GcrCertificateRequestClass GcrCertificateRequestClass;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrCertificateRequest {
|
|
Packit |
b00eeb |
GObject parent;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GckObject *private_key;
|
|
Packit |
b00eeb |
GNode *asn;
|
|
Packit |
b00eeb |
gulong *mechanisms;
|
|
Packit |
b00eeb |
gulong n_mechanisms;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
struct _GcrCertificateRequestClass {
|
|
Packit |
b00eeb |
GObjectClass parent_class;
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
enum {
|
|
Packit |
b00eeb |
PROP_0,
|
|
Packit |
b00eeb |
PROP_FORMAT,
|
|
Packit |
b00eeb |
PROP_PRIVATE_KEY
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Forward declarations */
|
|
Packit |
b00eeb |
G_DEFINE_TYPE (GcrCertificateRequest, gcr_certificate_request, G_TYPE_OBJECT);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* When updating here, update prepare_to_be_signed() */
|
|
Packit |
b00eeb |
static const gulong RSA_MECHANISMS[] = {
|
|
Packit |
b00eeb |
CKM_SHA1_RSA_PKCS,
|
|
Packit |
b00eeb |
CKM_RSA_PKCS,
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* When updating here, update prepare_to_be_signed() */
|
|
Packit |
b00eeb |
static const gulong DSA_MECHANISMS[] = {
|
|
Packit |
b00eeb |
CKM_DSA_SHA1,
|
|
Packit |
b00eeb |
CKM_DSA,
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static const gulong ALL_MECHANISMS[] = {
|
|
Packit |
b00eeb |
CKM_SHA1_RSA_PKCS,
|
|
Packit |
b00eeb |
CKM_DSA_SHA1,
|
|
Packit |
b00eeb |
CKM_RSA_PKCS,
|
|
Packit |
b00eeb |
CKM_DSA,
|
|
Packit |
b00eeb |
};
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_STATIC_ASSERT (sizeof (ALL_MECHANISMS) == sizeof (RSA_MECHANISMS) + sizeof (DSA_MECHANISMS));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_init (GcrCertificateRequest *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_constructed (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
|
|
Packit |
b00eeb |
GNode *version;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (gcr_certificate_request_parent_class)->constructed (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
self->asn = egg_asn1x_create (pkix_asn1_tab, "pkcs-10-CertificationRequest");
|
|
Packit |
b00eeb |
g_return_if_fail (self->asn != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Setup the version */
|
|
Packit |
b00eeb |
version = egg_asn1x_node (self->asn, "certificationRequestInfo", "version", NULL);
|
|
Packit |
b00eeb |
egg_asn1x_set_integer_as_ulong (version, 0);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_finalize (GObject *obj)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
egg_asn1x_destroy (self->asn);
|
|
Packit |
b00eeb |
g_free (self->mechanisms);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
G_OBJECT_CLASS (gcr_certificate_request_parent_class)->finalize (obj);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_set_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
const GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
|
|
Packit |
b00eeb |
GcrCertificateRequestFormat format;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_PRIVATE_KEY:
|
|
Packit |
b00eeb |
g_return_if_fail (self->private_key == NULL);
|
|
Packit |
b00eeb |
self->private_key = g_value_dup_object (value);
|
|
Packit |
b00eeb |
g_return_if_fail (GCK_IS_OBJECT (self->private_key));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_FORMAT:
|
|
Packit |
b00eeb |
format = g_value_get_enum (value);
|
|
Packit |
b00eeb |
g_return_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_get_property (GObject *obj,
|
|
Packit |
b00eeb |
guint prop_id,
|
|
Packit |
b00eeb |
GValue *value,
|
|
Packit |
b00eeb |
GParamSpec *pspec)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GcrCertificateRequest *self = GCR_CERTIFICATE_REQUEST (obj);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (prop_id) {
|
|
Packit |
b00eeb |
case PROP_PRIVATE_KEY:
|
|
Packit |
b00eeb |
g_value_set_object (value, gcr_certificate_request_get_private_key (self));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
case PROP_FORMAT:
|
|
Packit |
b00eeb |
g_value_set_enum (value, gcr_certificate_request_get_format (self));
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
|
|
Packit |
b00eeb |
break;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
gcr_certificate_request_class_init (GcrCertificateRequestClass *klass)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
gobject_class->constructed = gcr_certificate_request_constructed;
|
|
Packit |
b00eeb |
gobject_class->finalize = gcr_certificate_request_finalize;
|
|
Packit |
b00eeb |
gobject_class->set_property = gcr_certificate_request_set_property;
|
|
Packit |
b00eeb |
gobject_class->get_property = gcr_certificate_request_get_property;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrCertificateRequest:private-key:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The private key that this certificate request is for.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_PRIVATE_KEY,
|
|
Packit |
b00eeb |
g_param_spec_object ("private-key", "Private key", "Private key for request",
|
|
Packit |
b00eeb |
GCK_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* GcrCertificateRequest:format:
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* The format of the certificate request.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
g_object_class_install_property (gobject_class, PROP_FORMAT,
|
|
Packit |
b00eeb |
g_param_spec_enum ("format", "Format", "Format of certificate request",
|
|
Packit |
b00eeb |
GCR_TYPE_CERTIFICATE_REQUEST_FORMAT, GCR_CERTIFICATE_REQUEST_PKCS10,
|
|
Packit |
b00eeb |
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_prepare:
|
|
Packit |
b00eeb |
* @format: the format for the certificate request
|
|
Packit |
b00eeb |
* @private_key: the private key the the certificate is being requested for
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Create a new certificate request, in the given format for the private key.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full): a new #GcrCertificate request
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrCertificateRequest *
|
|
Packit |
b00eeb |
gcr_certificate_request_prepare (GcrCertificateRequestFormat format,
|
|
Packit |
b00eeb |
GckObject *private_key)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (format == GCR_CERTIFICATE_REQUEST_PKCS10, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCK_IS_OBJECT (private_key), NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_object_new (GCR_TYPE_CERTIFICATE_REQUEST,
|
|
Packit |
b00eeb |
"format", format,
|
|
Packit |
b00eeb |
"private-key", private_key,
|
|
Packit |
b00eeb |
NULL);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_get_private_key:
|
|
Packit |
b00eeb |
* @self: the certificate request
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Get the private key this certificate request is for.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer none): the private key,
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GckObject *
|
|
Packit |
b00eeb |
gcr_certificate_request_get_private_key (GcrCertificateRequest *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
|
|
Packit |
b00eeb |
return self->private_key;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_get_format:
|
|
Packit |
b00eeb |
* @self: the certificate request
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Get the format of this certificate request.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: the format
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
GcrCertificateRequestFormat
|
|
Packit |
b00eeb |
gcr_certificate_request_get_format (GcrCertificateRequest *self)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), 0);
|
|
Packit |
b00eeb |
return GCR_CERTIFICATE_REQUEST_PKCS10;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_set_cn:
|
|
Packit |
b00eeb |
* @self: the certificate request
|
|
Packit |
b00eeb |
* @cn: common name to set on the request
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Set the common name encoded in the certificate request.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_certificate_request_set_cn (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
const gchar *cn)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GNode *subject;
|
|
Packit |
b00eeb |
GNode *dn;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
|
|
Packit |
b00eeb |
g_return_if_fail (cn != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
subject = egg_asn1x_node (self->asn, "certificationRequestInfo", "subject", NULL);
|
|
Packit |
b00eeb |
dn = egg_asn1x_node (subject, "rdnSequence", NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* TODO: we shouldn't really be clearing this, but replacing CN */
|
|
Packit |
b00eeb |
egg_asn1x_set_choice (subject, dn);
|
|
Packit |
b00eeb |
egg_asn1x_clear (dn);
|
|
Packit |
b00eeb |
egg_dn_add_string_part (dn, GCR_OID_NAME_CN, cn);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GBytes *
|
|
Packit |
b00eeb |
hash_sha1_pkcs1 (GBytes *data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
const guchar SHA1_ASN[15] = /* Object ID is 1.3.14.3.2.26 */
|
|
Packit |
b00eeb |
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
|
Packit |
b00eeb |
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
GChecksum *checksum;
|
|
Packit |
b00eeb |
guchar *hash;
|
|
Packit |
b00eeb |
gsize n_hash;
|
|
Packit |
b00eeb |
gsize n_digest;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
n_digest = g_checksum_type_get_length (G_CHECKSUM_SHA1);
|
|
Packit |
b00eeb |
n_hash = n_digest + sizeof (SHA1_ASN);
|
|
Packit |
b00eeb |
hash = g_malloc (n_hash);
|
|
Packit |
b00eeb |
memcpy (hash, SHA1_ASN, sizeof (SHA1_ASN));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
checksum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
Packit |
b00eeb |
g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
|
|
Packit |
b00eeb |
g_checksum_get_digest (checksum, hash + sizeof (SHA1_ASN), &n_digest);
|
|
Packit |
b00eeb |
g_checksum_free (checksum);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_bytes_new_take (hash, n_hash);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GBytes *
|
|
Packit |
b00eeb |
hash_sha1 (GBytes *data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GChecksum *checksum;
|
|
Packit |
b00eeb |
guchar *hash;
|
|
Packit |
b00eeb |
gsize n_hash;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
n_hash = g_checksum_type_get_length (G_CHECKSUM_SHA1);
|
|
Packit |
b00eeb |
hash = g_malloc (n_hash);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
checksum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
Packit |
b00eeb |
g_checksum_update (checksum, g_bytes_get_data (data, NULL), g_bytes_get_size (data));
|
|
Packit |
b00eeb |
g_checksum_get_digest (checksum, hash, &n_hash);
|
|
Packit |
b00eeb |
g_checksum_free (checksum);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return g_bytes_new_take (hash, n_hash);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static GBytes *
|
|
Packit |
b00eeb |
prepare_to_be_signed (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GckMechanism *mechanism)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GNode *node;
|
|
Packit |
b00eeb |
GBytes *data;
|
|
Packit |
b00eeb |
GBytes *hash;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (mechanism != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (self->asn, "certificationRequestInfo", NULL);
|
|
Packit |
b00eeb |
data = egg_asn1x_encode (node, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
mechanism->parameter = NULL;
|
|
Packit |
b00eeb |
mechanism->n_parameter = 0;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
switch (mechanism->type) {
|
|
Packit |
b00eeb |
case CKM_SHA1_RSA_PKCS:
|
|
Packit |
b00eeb |
case CKM_DSA_SHA1:
|
|
Packit |
b00eeb |
return data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
case CKM_RSA_PKCS:
|
|
Packit |
b00eeb |
hash = hash_sha1_pkcs1 (data);
|
|
Packit |
b00eeb |
g_bytes_unref (data);
|
|
Packit |
b00eeb |
return hash;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
case CKM_DSA:
|
|
Packit |
b00eeb |
hash = hash_sha1 (data);
|
|
Packit |
b00eeb |
g_bytes_unref (data);
|
|
Packit |
b00eeb |
return hash;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
default:
|
|
Packit |
b00eeb |
g_assert_not_reached ();
|
|
Packit |
b00eeb |
return NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static gboolean
|
|
Packit |
b00eeb |
prepare_subject_public_key_and_mechanisms (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GNode *subject_public_key,
|
|
Packit |
b00eeb |
GQuark *algorithm,
|
|
Packit |
b00eeb |
const gulong **mechanisms,
|
|
Packit |
b00eeb |
gsize *n_mechanisms,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GBytes *encoded;
|
|
Packit |
b00eeb |
GNode *node;
|
|
Packit |
b00eeb |
GQuark oid;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_assert (algorithm != NULL);
|
|
Packit |
b00eeb |
g_assert (mechanisms != NULL);
|
|
Packit |
b00eeb |
g_assert (n_mechanisms != NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
encoded = egg_asn1x_encode (subject_public_key, NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (encoded != NULL, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (subject_public_key, "algorithm", "algorithm", NULL);
|
|
Packit |
b00eeb |
oid = egg_asn1x_get_oid_as_quark (node);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (oid == GCR_OID_PKIX1_RSA) {
|
|
Packit |
b00eeb |
*mechanisms = RSA_MECHANISMS;
|
|
Packit |
b00eeb |
*n_mechanisms = G_N_ELEMENTS (RSA_MECHANISMS);
|
|
Packit |
b00eeb |
*algorithm = GCR_OID_PKIX1_SHA1_WITH_RSA;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else if (oid == GCR_OID_PKIX1_DSA) {
|
|
Packit |
b00eeb |
*mechanisms = DSA_MECHANISMS;
|
|
Packit |
b00eeb |
*n_mechanisms = G_N_ELEMENTS (DSA_MECHANISMS);
|
|
Packit |
b00eeb |
*algorithm = GCR_OID_PKIX1_SHA1_WITH_DSA;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_bytes_unref (encoded);
|
|
Packit |
b00eeb |
g_set_error (error, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
|
|
Packit |
b00eeb |
_("Unsupported key type for certificate request"));
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (self->asn, "certificationRequestInfo", "subjectPKInfo", NULL);
|
|
Packit |
b00eeb |
if (!egg_asn1x_decode (node, encoded))
|
|
Packit |
b00eeb |
g_return_val_if_reached (FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_bytes_unref (encoded);
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
encode_take_signature_into_request (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GQuark algorithm,
|
|
Packit |
b00eeb |
GNode *subject_public_key,
|
|
Packit |
b00eeb |
guchar *result,
|
|
Packit |
b00eeb |
gsize n_result)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GNode *params;
|
|
Packit |
b00eeb |
GNode *node;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (self->asn, "signature", NULL);
|
|
Packit |
b00eeb |
egg_asn1x_take_bits_as_raw (node, g_bytes_new_take (result, n_result), n_result * 8);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (self->asn, "signatureAlgorithm", "algorithm", NULL);
|
|
Packit |
b00eeb |
egg_asn1x_set_oid_as_quark (node, algorithm);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
node = egg_asn1x_node (self->asn, "signatureAlgorithm", "parameters", NULL);
|
|
Packit |
b00eeb |
params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
|
|
Packit |
b00eeb |
egg_asn1x_set_any_from (node, params);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_complete:
|
|
Packit |
b00eeb |
* @self: a certificate request
|
|
Packit |
b00eeb |
* @cancellable: a cancellation object
|
|
Packit |
b00eeb |
* @error: location to place an error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Complete and sign a certificate request, so that it can be encoded
|
|
Packit |
b00eeb |
* and sent to a certificate authority.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This call may block as it signs the request using the private key.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether certificate request was successfully completed or not
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_certificate_request_complete (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GNode *subject_public_key;
|
|
Packit |
b00eeb |
const gulong *mechanisms;
|
|
Packit |
b00eeb |
gsize n_mechanisms;
|
|
Packit |
b00eeb |
GckMechanism mechanism = { 0, };
|
|
Packit |
b00eeb |
GQuark algorithm = 0;
|
|
Packit |
b00eeb |
GBytes *tbs;
|
|
Packit |
b00eeb |
GckSession *session;
|
|
Packit |
b00eeb |
guchar *signature;
|
|
Packit |
b00eeb |
gsize n_signature;
|
|
Packit |
b00eeb |
gboolean ret;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
subject_public_key = _gcr_subject_public_key_load (self->private_key,
|
|
Packit |
b00eeb |
cancellable, error);
|
|
Packit |
b00eeb |
if (subject_public_key == NULL)
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
ret = prepare_subject_public_key_and_mechanisms (self, subject_public_key,
|
|
Packit |
b00eeb |
&algorithm, &mechanisms,
|
|
Packit |
b00eeb |
&n_mechanisms, error);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!ret) {
|
|
Packit |
b00eeb |
egg_asn1x_destroy (subject_public_key);
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/* Figure out which mechanism to use */
|
|
Packit |
b00eeb |
mechanism.type = _gcr_key_mechanisms_check (self->private_key, mechanisms,
|
|
Packit |
b00eeb |
n_mechanisms, CKA_SIGN,
|
|
Packit |
b00eeb |
cancellable, NULL);
|
|
Packit |
b00eeb |
if (mechanism.type == GCK_INVALID) {
|
|
Packit |
b00eeb |
egg_asn1x_destroy (subject_public_key);
|
|
Packit |
b00eeb |
g_set_error (error, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
|
|
Packit |
b00eeb |
_("The key cannot be used to sign the request"));
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
tbs = prepare_to_be_signed (self, &mechanism);
|
|
Packit |
b00eeb |
session = gck_object_get_session (self->private_key);
|
|
Packit |
b00eeb |
signature = gck_session_sign_full (session, self->private_key, &mechanism,
|
|
Packit |
b00eeb |
g_bytes_get_data (tbs, NULL),
|
|
Packit |
b00eeb |
g_bytes_get_size (tbs),
|
|
Packit |
b00eeb |
&n_signature, cancellable, error);
|
|
Packit |
b00eeb |
g_object_unref (session);
|
|
Packit |
b00eeb |
g_bytes_unref (tbs);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (!signature) {
|
|
Packit |
b00eeb |
egg_asn1x_destroy (subject_public_key);
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
encode_take_signature_into_request (self, algorithm, subject_public_key,
|
|
Packit |
b00eeb |
signature, n_signature);
|
|
Packit |
b00eeb |
egg_asn1x_destroy (subject_public_key);
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
typedef struct {
|
|
Packit |
b00eeb |
GcrCertificateRequest *request;
|
|
Packit |
b00eeb |
GCancellable *cancellable;
|
|
Packit |
b00eeb |
GQuark algorithm;
|
|
Packit |
b00eeb |
GNode *subject_public_key;
|
|
Packit |
b00eeb |
GckMechanism mechanism;
|
|
Packit |
b00eeb |
GckSession *session;
|
|
Packit |
b00eeb |
GBytes *tbs;
|
|
Packit |
b00eeb |
} CompleteClosure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
complete_closure_free (gpointer data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
CompleteClosure *closure = data;
|
|
Packit |
b00eeb |
egg_asn1x_destroy (closure->subject_public_key);
|
|
Packit |
b00eeb |
g_clear_object (&closure->request);
|
|
Packit |
b00eeb |
g_clear_object (&closure->cancellable);
|
|
Packit |
b00eeb |
g_clear_object (&closure->session);
|
|
Packit |
b00eeb |
if (closure->tbs)
|
|
Packit |
b00eeb |
g_bytes_unref (closure->tbs);
|
|
Packit |
b00eeb |
g_free (closure);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_certificate_request_signed (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
guchar *signature;
|
|
Packit |
b00eeb |
gsize n_signature;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
signature = gck_session_sign_finish (closure->session, result, &n_signature, &error);
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
encode_take_signature_into_request (closure->request,
|
|
Packit |
b00eeb |
closure->algorithm,
|
|
Packit |
b00eeb |
closure->subject_public_key,
|
|
Packit |
b00eeb |
signature, n_signature);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
g_simple_async_result_take_error (res, error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_mechanism_check (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure->mechanism.type = _gcr_key_mechanisms_check_finish (closure->request->private_key,
|
|
Packit |
b00eeb |
result, NULL);
|
|
Packit |
b00eeb |
if (closure->mechanism.type == GCK_INVALID) {
|
|
Packit |
b00eeb |
g_simple_async_result_set_error (res, GCK_ERROR, CKR_KEY_TYPE_INCONSISTENT,
|
|
Packit |
b00eeb |
_("The key cannot be used to sign the request"));
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
closure->tbs = prepare_to_be_signed (closure->request, &closure->mechanism);
|
|
Packit |
b00eeb |
gck_session_sign_async (closure->session,
|
|
Packit |
b00eeb |
closure->request->private_key,
|
|
Packit |
b00eeb |
&closure->mechanism,
|
|
Packit |
b00eeb |
g_bytes_get_data (closure->tbs, NULL),
|
|
Packit |
b00eeb |
g_bytes_get_size (closure->tbs),
|
|
Packit |
b00eeb |
closure->cancellable,
|
|
Packit |
b00eeb |
on_certificate_request_signed,
|
|
Packit |
b00eeb |
g_object_ref (res));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
static void
|
|
Packit |
b00eeb |
on_subject_public_key_loaded (GObject *source,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
|
|
Packit |
b00eeb |
CompleteClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
|
|
Packit |
b00eeb |
const gulong *mechanisms;
|
|
Packit |
b00eeb |
gsize n_mechanisms;
|
|
Packit |
b00eeb |
GError *error = NULL;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
closure->subject_public_key = _gcr_subject_public_key_load_finish (result, &error);
|
|
Packit |
b00eeb |
if (error == NULL) {
|
|
Packit |
b00eeb |
prepare_subject_public_key_and_mechanisms (closure->request,
|
|
Packit |
b00eeb |
closure->subject_public_key,
|
|
Packit |
b00eeb |
&closure->algorithm,
|
|
Packit |
b00eeb |
&mechanisms,
|
|
Packit |
b00eeb |
&n_mechanisms,
|
|
Packit |
b00eeb |
&error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (error != NULL) {
|
|
Packit |
b00eeb |
g_simple_async_result_take_error (res, error);
|
|
Packit |
b00eeb |
g_simple_async_result_complete (res);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
_gcr_key_mechanisms_check_async (closure->request->private_key,
|
|
Packit |
b00eeb |
mechanisms, n_mechanisms, CKA_SIGN,
|
|
Packit |
b00eeb |
closure->cancellable, on_mechanism_check,
|
|
Packit |
b00eeb |
g_object_ref (res));
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_complete_async:
|
|
Packit |
b00eeb |
* @self: a certificate request
|
|
Packit |
b00eeb |
* @cancellable: a cancellation object
|
|
Packit |
b00eeb |
* @callback: called when the operation completes
|
|
Packit |
b00eeb |
* @user_data: data to pass to the callback
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Asynchronously complete and sign a certificate request, so that it can
|
|
Packit |
b00eeb |
* be encoded and sent to a certificate authority.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* This call will return immediately and complete later.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_certificate_request_complete_async (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GSimpleAsyncResult *res;
|
|
Packit |
b00eeb |
CompleteClosure *closure;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_if_fail (GCR_IS_CERTIFICATE_REQUEST (self));
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
|
Packit |
b00eeb |
gcr_certificate_request_complete_async);
|
|
Packit |
b00eeb |
closure = g_new0 (CompleteClosure, 1);
|
|
Packit |
b00eeb |
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
|
Packit |
b00eeb |
closure->session = gck_object_get_session (self->private_key);
|
|
Packit |
b00eeb |
closure->request = g_object_ref (self);
|
|
Packit |
b00eeb |
g_simple_async_result_set_op_res_gpointer (res, closure, complete_closure_free);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
_gcr_subject_public_key_load_async (self->private_key, cancellable,
|
|
Packit |
b00eeb |
on_subject_public_key_loaded,
|
|
Packit |
b00eeb |
g_object_ref (res));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_object_unref (res);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_complete_finish:
|
|
Packit |
b00eeb |
* @self: a certificate request
|
|
Packit |
b00eeb |
* @result: result of the asynchronous operation
|
|
Packit |
b00eeb |
* @error: location to place an error on failure
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Finish an asynchronous operation to complete and sign a certificate
|
|
Packit |
b00eeb |
* request.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether certificate request was successfully completed or not
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_certificate_request_complete_finish (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
|
Packit |
b00eeb |
gcr_certificate_request_complete_async), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
|
|
Packit |
b00eeb |
return FALSE;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return TRUE;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_encode:
|
|
Packit |
b00eeb |
* @self: a certificate request
|
|
Packit |
b00eeb |
* @textual: whether to encode output as text
|
|
Packit |
b00eeb |
* @length: location to place length of returned data
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Encode the certificate request. It must have been completed with
|
|
Packit |
b00eeb |
* gcr_certificate_request_complete() or gcr_certificate_request_complete_async()
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* If @textual is %FALSE, the output is a DER encoded certificate request.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* If @textual is %TRUE, the output is encoded as text. For PKCS\#10 requests this
|
|
Packit |
b00eeb |
* is done using the OpenSSL style PEM encoding.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: (transfer full) (array length=length): the encoded certificate request
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
guchar *
|
|
Packit |
b00eeb |
gcr_certificate_request_encode (GcrCertificateRequest *self,
|
|
Packit |
b00eeb |
gboolean textual,
|
|
Packit |
b00eeb |
gsize *length)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GBytes *bytes;
|
|
Packit |
b00eeb |
gpointer encoded;
|
|
Packit |
b00eeb |
gpointer data;
|
|
Packit |
b00eeb |
gsize size;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCR_IS_CERTIFICATE_REQUEST (self), NULL);
|
|
Packit |
b00eeb |
g_return_val_if_fail (length != NULL, NULL);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
bytes = egg_asn1x_encode (self->asn, NULL);
|
|
Packit |
b00eeb |
if (bytes == NULL) {
|
|
Packit |
b00eeb |
g_warning ("couldn't encode certificate request: %s",
|
|
Packit |
b00eeb |
egg_asn1x_message (self->asn));
|
|
Packit |
b00eeb |
return NULL;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
size = g_bytes_get_size (bytes);
|
|
Packit |
b00eeb |
encoded = g_byte_array_free (g_bytes_unref_to_array (bytes), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
if (textual) {
|
|
Packit |
b00eeb |
data = egg_armor_write (encoded, size,
|
|
Packit |
b00eeb |
g_quark_from_static_string ("CERTIFICATE REQUEST"),
|
|
Packit |
b00eeb |
NULL, length);
|
|
Packit |
b00eeb |
g_free (encoded);
|
|
Packit |
b00eeb |
encoded = data;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
} else {
|
|
Packit |
b00eeb |
*length = size;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return encoded;
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_capable:
|
|
Packit |
b00eeb |
* @private_key: a private key
|
|
Packit |
b00eeb |
* @cancellable: cancellation object
|
|
Packit |
b00eeb |
* @error: location to place an error
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Check whether #GcrCertificateRequest is capable of creating a request
|
|
Packit |
b00eeb |
* for the given @private_key.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether a request can be created
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_certificate_request_capable (GckObject *private_key,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_val_if_fail (GCK_IS_OBJECT (private_key), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
|
Packit |
b00eeb |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return _gcr_key_mechanisms_check (private_key, ALL_MECHANISMS,
|
|
Packit |
b00eeb |
G_N_ELEMENTS (ALL_MECHANISMS),
|
|
Packit |
b00eeb |
CKA_SIGN, cancellable, error);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_capable_async:
|
|
Packit |
b00eeb |
* @private_key: a private key
|
|
Packit |
b00eeb |
* @cancellable: cancellation object
|
|
Packit |
b00eeb |
* @callback: will be called when the operation completes
|
|
Packit |
b00eeb |
* @user_data: data to be passed to callback
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Asynchronously check whether #GcrCertificateRequest is capable of creating
|
|
Packit |
b00eeb |
* a request for the given @private_key.
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
void
|
|
Packit |
b00eeb |
gcr_certificate_request_capable_async (GckObject *private_key,
|
|
Packit |
b00eeb |
GCancellable *cancellable,
|
|
Packit |
b00eeb |
GAsyncReadyCallback callback,
|
|
Packit |
b00eeb |
gpointer user_data)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
g_return_if_fail (GCK_IS_OBJECT (private_key));
|
|
Packit |
b00eeb |
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
_gcr_key_mechanisms_check_async (private_key, ALL_MECHANISMS,
|
|
Packit |
b00eeb |
G_N_ELEMENTS (ALL_MECHANISMS),
|
|
Packit |
b00eeb |
CKA_SIGN, cancellable,
|
|
Packit |
b00eeb |
callback, user_data);
|
|
Packit |
b00eeb |
}
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
/**
|
|
Packit |
b00eeb |
* gcr_certificate_request_capable_finish:
|
|
Packit |
b00eeb |
* @result: asynchronous result
|
|
Packit |
b00eeb |
* @error: location to place an error
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Get the result for asynchronously check whether #GcrCertificateRequest is
|
|
Packit |
b00eeb |
* capable of creating a request for the given @private_key.
|
|
Packit |
b00eeb |
*
|
|
Packit |
b00eeb |
* Returns: whether a request can be created
|
|
Packit |
b00eeb |
*/
|
|
Packit |
b00eeb |
gboolean
|
|
Packit |
b00eeb |
gcr_certificate_request_capable_finish (GAsyncResult *result,
|
|
Packit |
b00eeb |
GError **error)
|
|
Packit |
b00eeb |
{
|
|
Packit |
b00eeb |
GObject *source;
|
|
Packit |
b00eeb |
gulong mech;
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
source = g_async_result_get_source_object (result);
|
|
Packit |
b00eeb |
mech = _gcr_key_mechanisms_check_finish (GCK_OBJECT (source), result, error);
|
|
Packit |
b00eeb |
g_object_unref (source);
|
|
Packit |
b00eeb |
|
|
Packit |
b00eeb |
return mech != GCK_INVALID;
|
|
Packit |
b00eeb |
}
|