static GObject* gkm_certificate_constructor (GType type, guint n_props, GObjectConstructParam *props) { GkmCertificate *self = GKM_CERTIFICATE (G_OBJECT_CLASS (gkm_certificate_parent_class)->constructor(type, n_props, props)); g_return_val_if_fail (self, NULL); return G_OBJECT (self); }
static GkmCertificate* add_certificate_for_data (GkmRootsModule *self, const guchar *data, gsize n_data, const gchar *path) { GkmCertificate *cert; GkmManager *manager; gchar *hash, *unique; g_assert (GKM_IS_ROOTS_MODULE (self)); g_assert (data); g_assert (path); manager = gkm_module_get_manager (GKM_MODULE (self)); g_return_val_if_fail (manager, NULL); /* Hash the certificate */ hash = g_compute_checksum_for_data (G_CHECKSUM_MD5, data, n_data); unique = g_strdup_printf ("%s:%s", path, hash); g_free (hash); /* Try and find a certificate */ cert = GKM_CERTIFICATE (gkm_manager_find_one_by_string_property (manager, "unique", unique)); if (cert != NULL) { g_free (unique); return cert; } /* Create a new certificate object */ cert = GKM_CERTIFICATE (gkm_roots_certificate_new (GKM_MODULE (self), unique, path)); g_free (unique); if (!gkm_serializable_load (GKM_SERIALIZABLE (cert), NULL, data, n_data)) { g_message ("couldn't parse certificate(s): %s", path); g_object_unref (cert); return NULL; } /* Make the certificate show up */ gkm_object_expose (GKM_OBJECT (cert), TRUE); /* And add to our wonderful table */ g_hash_table_insert (self->certificates, cert, cert); return cert; }
static void gkm_certificate_dispose (GObject *obj) { GkmCertificate *self = GKM_CERTIFICATE (obj); if (self->pv->key) g_object_unref (self->pv->key); self->pv->key = NULL; G_OBJECT_CLASS (gkm_certificate_parent_class)->dispose (obj); }
static void gkm_certificate_finalize (GObject *obj) { GkmCertificate *self = GKM_CERTIFICATE (obj); g_assert (!self->pv->key); g_free (self->pv->data); g_free (self->pv->label); egg_asn1x_destroy (self->pv->asn1); G_OBJECT_CLASS (gkm_certificate_parent_class)->finalize (obj); }
static GObject* gkm_roots_certificate_constructor (GType type, guint n_props, GObjectConstructParam *props) { GkmRootsCertificate *self = GKM_ROOTS_CERTIFICATE (G_OBJECT_CLASS (gkm_roots_certificate_parent_class)->constructor(type, n_props, props)); g_return_val_if_fail (self, NULL); self->trust = gkm_roots_trust_new (gkm_object_get_module (GKM_OBJECT (self)), gkm_object_get_manager (GKM_OBJECT (self)), GKM_CERTIFICATE (self)); return G_OBJECT (self); }
static gboolean gkm_certificate_real_save (GkmSerializable *base, GkmSecret *login, gpointer *data, gsize *n_data) { GkmCertificate *self = GKM_CERTIFICATE (base); g_return_val_if_fail (GKM_IS_CERTIFICATE (self), FALSE); g_return_val_if_fail (data, FALSE); g_return_val_if_fail (n_data, FALSE); *n_data = self->pv->n_data; *data = g_memdup (self->pv->data, self->pv->n_data); return TRUE; }
static void gkm_certificate_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec) { GkmCertificate *self = GKM_CERTIFICATE (obj); switch (prop_id) { case PROP_LABEL: gkm_certificate_set_label (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; } }
static CK_RV gkm_roots_certificate_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE_PTR attr) { GkmRootsCertificate *self = GKM_ROOTS_CERTIFICATE (base); CK_ULONG category; switch (attr->type) { case CKA_TRUSTED: return gkm_attribute_set_bool (attr, TRUE); case CKA_CERTIFICATE_CATEGORY: if (!gkm_certificate_calc_category (GKM_CERTIFICATE (self), session, &category)) return CKR_FUNCTION_FAILED; /* Unknown category, is CA by default in this slot */ if (category == 0) category = 2; return gkm_attribute_set_ulong (attr, category); } return GKM_OBJECT_CLASS (gkm_roots_certificate_parent_class)->get_attribute (base, session, attr); }
static gboolean gkm_certificate_real_load (GkmSerializable *base, GkmSecret *login, gconstpointer data, gsize n_data) { GkmCertificate *self = GKM_CERTIFICATE (base); GNode *asn1 = NULL; GkmDataResult res; guchar *copy, *keydata; gsize n_keydata; gcry_sexp_t sexp; GkmSexp *wrapper; g_return_val_if_fail (GKM_IS_CERTIFICATE (self), FALSE); if (!data || !n_data) { g_message ("cannot load empty certificate file"); return FALSE; } copy = g_memdup (data, n_data); /* Parse the ASN1 data */ res = gkm_data_der_read_certificate (copy, n_data, &asn1); if (res != GKM_DATA_SUCCESS) { g_message ("couldn't parse certificate data"); g_free (copy); return FALSE; } /* Generate a raw public key from our certificate */ keydata = egg_asn1x_encode (egg_asn1x_node (asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), NULL, &n_keydata); g_return_val_if_fail (keydata, FALSE); /* Now create us a nice public key with that identifier */ res = gkm_data_der_read_public_key_info (keydata, n_keydata, &sexp); g_free (keydata); switch (res) { /* Create ourselves a public key with that */ case GKM_DATA_SUCCESS: wrapper = gkm_sexp_new (sexp); if (!self->pv->key) self->pv->key = gkm_certificate_key_new (gkm_object_get_module (GKM_OBJECT (self)), gkm_object_get_manager (GKM_OBJECT (self)), self); gkm_sexp_key_set_base (GKM_SEXP_KEY (self->pv->key), wrapper); gkm_sexp_unref (wrapper); break; /* Unknown type of public key for this certificate, just ignore */ case GKM_DATA_UNRECOGNIZED: if (self->pv->key) g_object_unref (self->pv->key); self->pv->key = NULL; break; /* Bad key, drop certificate */ case GKM_DATA_FAILURE: case GKM_DATA_LOCKED: g_warning ("couldn't parse certificate key data"); g_free (copy); egg_asn1x_destroy (asn1); return FALSE; default: g_assert_not_reached (); break; } g_free (self->pv->data); self->pv->data = copy; self->pv->n_data = n_data; egg_asn1x_destroy (self->pv->asn1); self->pv->asn1 = asn1; return TRUE; }
static CK_RV gkm_certificate_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr) { GkmCertificate *self = GKM_CERTIFICATE (base); CK_ULONG category; const guchar *cdata; guchar *data; gsize n_data; time_t when; CK_RV rv; switch (attr->type) { case CKA_CLASS: return gkm_attribute_set_ulong (attr, CKO_CERTIFICATE); case CKA_PRIVATE: return gkm_attribute_set_bool (attr, FALSE); case CKA_LABEL: return gkm_attribute_set_string (attr, gkm_certificate_get_label (self)); case CKA_CERTIFICATE_TYPE: return gkm_attribute_set_ulong (attr, CKC_X_509); case CKA_TRUSTED: return gkm_attribute_set_bool (attr, FALSE); case CKA_CERTIFICATE_CATEGORY: if (!gkm_certificate_calc_category (self, session, &category)) return CKR_FUNCTION_FAILED; return gkm_attribute_set_ulong (attr, category); case CKA_CHECK_VALUE: g_return_val_if_fail (self->pv->data, CKR_GENERAL_ERROR); n_data = gcry_md_get_algo_dlen (GCRY_MD_SHA1); g_return_val_if_fail (n_data && n_data > 3, CKR_GENERAL_ERROR); data = g_new0 (guchar, n_data); gcry_md_hash_buffer (GCRY_MD_SHA1, data, self->pv->data, self->pv->n_data); rv = gkm_attribute_set_data (attr, data, 3); g_free (data); return rv; case CKA_START_DATE: case CKA_END_DATE: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); when = egg_asn1x_get_time_as_long (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "validity", attr->type == CKA_START_DATE ? "notBefore" : "notAfter", NULL)); if (when < 0) return CKR_FUNCTION_FAILED; return gkm_attribute_set_date (attr, when); case CKA_SUBJECT: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "subject", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_ID: if (!self->pv->key) return gkm_attribute_set_data (attr, NULL, 0); return gkm_object_get_attribute (GKM_OBJECT (self->pv->key), session, attr); case CKA_ISSUER: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "issuer", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_SERIAL_NUMBER: g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR); cdata = egg_asn1x_get_raw_element (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "serialNumber", NULL), &n_data); g_return_val_if_fail (cdata, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, cdata, n_data); case CKA_VALUE: g_return_val_if_fail (self->pv->data, CKR_GENERAL_ERROR); return gkm_attribute_set_data (attr, self->pv->data, self->pv->n_data); /* These are only used for strange online certificates which we don't support */ case CKA_URL: case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: case CKA_HASH_OF_ISSUER_PUBLIC_KEY: return gkm_attribute_set_data (attr, "", 0); /* What in the world is this doing in the spec? */ case CKA_JAVA_MIDP_SECURITY_DOMAIN: return gkm_attribute_set_ulong (attr, 0); /* 0 = unspecified */ }; return GKM_OBJECT_CLASS (gkm_certificate_parent_class)->get_attribute (base, session, attr); }