LCOV - code coverage report
Current view: top level - pkcs11/gkm - gkm-certificate.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 56.7 % 284 161
Test Date: 2024-04-08 13:24:42 Functions: 69.2 % 26 18

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program is free software; you can redistribute it and/or modify
       7              :  * it under the terms of the GNU Lesser General Public License as
       8              :  * published by the Free Software Foundation; either version 2.1 of
       9              :  * the License, or (at your option) any later version.
      10              :  *
      11              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * Lesser General Public License for more details.
      15              :  *
      16              :  * You should have received a copy of the GNU Lesser General Public
      17              :  * License along with this program; if not, see
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "gkm-attributes.h"
      24              : #include "gkm-certificate.h"
      25              : #include "gkm-certificate-key.h"
      26              : #include "gkm-crypto.h"
      27              : #include "gkm-data-asn1.h"
      28              : #include "gkm-data-der.h"
      29              : #define DEBUG_FLAG GKM_DEBUG_STORAGE
      30              : #include "gkm-debug.h"
      31              : #include "gkm-factory.h"
      32              : #include "gkm-sexp-key.h"
      33              : #include "gkm-manager.h"
      34              : #include "gkm-session.h"
      35              : #include "gkm-sexp.h"
      36              : #include "gkm-serializable.h"
      37              : #include "gkm-transaction.h"
      38              : #include "gkm-util.h"
      39              : 
      40              : #include "egg/egg-dn.h"
      41              : #include "egg/egg-asn1x.h"
      42              : 
      43              : #include "pkcs11/pkcs11.h"
      44              : #include "pkcs11/pkcs11i.h"
      45              : 
      46              : #include <glib/gi18n.h>
      47              : 
      48              : enum {
      49              :         PROP_0,
      50              :         PROP_LABEL,
      51              :         PROP_PUBLIC_KEY
      52              : };
      53              : 
      54              : struct _GkmCertificatePrivate {
      55              :         GkmCertificateKey *key;
      56              :         GNode *asn1;
      57              :         GBytes *der;
      58              :         gchar *label;
      59              : };
      60              : 
      61              : static GQuark OID_BASIC_CONSTRAINTS;
      62              : static GQuark OID_ENHANCED_USAGE;
      63              : 
      64              : static void gkm_certificate_serializable (GkmSerializableIface *iface);
      65              : 
      66          452 : G_DEFINE_TYPE_EXTENDED (GkmCertificate, gkm_certificate, GKM_TYPE_OBJECT, 0,
      67              :                G_ADD_PRIVATE (GkmCertificate)
      68              :                G_IMPLEMENT_INTERFACE (GKM_TYPE_SERIALIZABLE, gkm_certificate_serializable));
      69              : 
      70              : /* -----------------------------------------------------------------------------
      71              :  * INTERNAL
      72              :  */
      73              : 
      74              : static void
      75            6 : init_quarks (void)
      76              : {
      77              :         static gsize quarks_inited = 0;
      78              : 
      79            6 :         if (g_once_init_enter (&quarks_inited)) {
      80              :                 #define QUARK(name, value) \
      81              :                         name = g_quark_from_static_string(value)
      82              : 
      83            6 :                 QUARK (OID_BASIC_CONSTRAINTS, "2.5.29.19");
      84            6 :                 QUARK (OID_ENHANCED_USAGE, "2.5.29.37");
      85              : 
      86              :                 #undef QUARK
      87              : 
      88            6 :                 g_once_init_leave (&quarks_inited, 1);
      89              :         }
      90            6 : }
      91              : 
      92              : static gint
      93            0 : find_certificate_extension (GkmCertificate *self, GQuark oid)
      94              : {
      95              :         GQuark exoid;
      96              :         GNode *node;
      97              :         guint index;
      98              : 
      99            0 :         g_assert (oid);
     100            0 :         g_assert (GKM_IS_CERTIFICATE (self));
     101            0 :         g_assert (self->pv->asn1);
     102              : 
     103            0 :         for (index = 1; TRUE; ++index) {
     104              : 
     105              :                 /* Make sure it is present */
     106            0 :                 node = egg_asn1x_node (self->pv->asn1, "tbsCertificate", "extensions", index, NULL);
     107            0 :                 if (node == NULL)
     108            0 :                         break;
     109              : 
     110              :                 /* See if it's the same */
     111            0 :                 exoid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (node, "extnID", NULL));
     112              : 
     113            0 :                 if(exoid == oid)
     114            0 :                         return index;
     115              :         }
     116              : 
     117            0 :         return 0;
     118              : }
     119              : 
     120              : static GkmObject*
     121           10 : factory_create_certificate (GkmSession *session, GkmTransaction *transaction,
     122              :                             CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
     123              : {
     124              :         CK_ATTRIBUTE_PTR attr;
     125              :         GkmCertificate *cert;
     126              :         GBytes *bytes;
     127              :         gboolean ret;
     128              : 
     129           10 :         g_return_val_if_fail (GKM_IS_TRANSACTION (transaction), NULL);
     130           10 :         g_return_val_if_fail (attrs || !n_attrs, NULL);
     131              : 
     132              :         /* Dig out the value */
     133           10 :         attr = gkm_attributes_find (attrs, n_attrs, CKA_VALUE);
     134           10 :         if (attr == NULL) {
     135            0 :                 gkm_transaction_fail (transaction, CKR_TEMPLATE_INCOMPLETE);
     136            0 :                 return NULL;
     137              :         }
     138              : 
     139           10 :         cert = g_object_new (GKM_TYPE_CERTIFICATE,
     140              :                              "module", gkm_session_get_module (session),
     141              :                              "manager", gkm_manager_for_template (attrs, n_attrs, session),
     142              :                              NULL);
     143              : 
     144              :         /* Load the certificate from the data specified */
     145           10 :         bytes = g_bytes_new (attr->pValue, attr->ulValueLen);
     146           10 :         ret = gkm_serializable_load (GKM_SERIALIZABLE (cert), NULL, bytes);
     147           10 :         g_bytes_unref (bytes);
     148              : 
     149           10 :         if(!ret) {
     150            0 :                 gkm_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
     151            0 :                 g_object_unref (cert);
     152            0 :                 return NULL;
     153              :         }
     154              : 
     155              :         /* We calculate these attributes automatically */
     156           10 :         gkm_attributes_consume (attrs, n_attrs,
     157              :                                 CKA_VALUE, CKA_SUBJECT, CKA_SERIAL_NUMBER, CKA_ID,
     158              :                                 G_MAXULONG);
     159              : 
     160           10 :         gkm_session_complete_object_creation (session, transaction, GKM_OBJECT (cert),
     161              :                                               TRUE, attrs, n_attrs);
     162           10 :         return GKM_OBJECT (cert);
     163              : }
     164              : 
     165              : /* -----------------------------------------------------------------------------
     166              :  * KEY
     167              :  */
     168              : 
     169              : static CK_RV
     170          178 : gkm_certificate_real_get_attribute (GkmObject *base, GkmSession *session, CK_ATTRIBUTE* attr)
     171              : {
     172          178 :         GkmCertificate *self = GKM_CERTIFICATE (base);
     173              :         CK_ULONG category;
     174              :         GBytes *cdata;
     175              :         guchar *data;
     176              :         gsize n_data;
     177              :         time_t when;
     178              :         CK_RV rv;
     179              : 
     180          178 :         switch (attr->type) {
     181              : 
     182           62 :         case CKA_CLASS:
     183           62 :                 return gkm_attribute_set_ulong (attr, CKO_CERTIFICATE);
     184              : 
     185           16 :         case CKA_PRIVATE:
     186           16 :                 return gkm_attribute_set_bool (attr, FALSE);
     187              : 
     188            2 :         case CKA_LABEL:
     189            2 :                 return gkm_attribute_set_string (attr, gkm_certificate_get_label (self));
     190              : 
     191            9 :         case CKA_CERTIFICATE_TYPE:
     192            9 :                 return gkm_attribute_set_ulong (attr, CKC_X_509);
     193              : 
     194            0 :         case CKA_TRUSTED:
     195            0 :                 return gkm_attribute_set_bool (attr, FALSE);
     196              : 
     197            0 :         case CKA_CERTIFICATE_CATEGORY:
     198            0 :                 if (!gkm_certificate_calc_category (self, session, &category))
     199            0 :                         return CKR_FUNCTION_FAILED;
     200            0 :                 return gkm_attribute_set_ulong (attr, category);
     201              : 
     202            2 :         case CKA_CHECK_VALUE:
     203            2 :                 g_return_val_if_fail (self->pv->der != NULL, CKR_GENERAL_ERROR);
     204            2 :                 n_data = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
     205            2 :                 g_return_val_if_fail (n_data && n_data > 3, CKR_GENERAL_ERROR);
     206            2 :                 data = g_new0 (guchar, n_data);
     207            2 :                 gcry_md_hash_buffer (GCRY_MD_SHA1, data,
     208            2 :                                      g_bytes_get_data (self->pv->der, NULL),
     209            2 :                                      g_bytes_get_size (self->pv->der));
     210            2 :                 rv = gkm_attribute_set_data (attr, data, 3);
     211            2 :                 g_free (data);
     212            2 :                 return rv;
     213              : 
     214            0 :         case CKA_START_DATE:
     215              :         case CKA_END_DATE:
     216            0 :                 g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR);
     217            0 :                 when = egg_asn1x_get_time_as_long (egg_asn1x_node (self->pv->asn1,
     218              :                                                                    "tbsCertificate", "validity",
     219            0 :                                                                    attr->type == CKA_START_DATE ? "notBefore" : "notAfter",
     220              :                                                                    NULL));
     221            0 :                 if (when < 0)
     222            0 :                         return CKR_FUNCTION_FAILED;
     223            0 :                 return gkm_attribute_set_date (attr, when);
     224              : 
     225           12 :         case CKA_SUBJECT:
     226           12 :                 g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR);
     227           12 :                 cdata = egg_asn1x_get_element_raw (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "subject", NULL));
     228           12 :                 g_return_val_if_fail (cdata, CKR_GENERAL_ERROR);
     229           12 :                 rv = gkm_attribute_set_bytes (attr, cdata);
     230           12 :                 g_bytes_unref (cdata);
     231           12 :                 return rv;
     232              : 
     233           54 :         case CKA_ID:
     234           54 :                 if (!self->pv->key)
     235            0 :                         return gkm_attribute_set_data (attr, NULL, 0);
     236           54 :                 return gkm_object_get_attribute (GKM_OBJECT (self->pv->key), session, attr);
     237              : 
     238            4 :         case CKA_ISSUER:
     239            4 :                 g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR);
     240            4 :                 cdata = egg_asn1x_get_element_raw (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "issuer", NULL));
     241            4 :                 g_return_val_if_fail (cdata, CKR_GENERAL_ERROR);
     242            4 :                 rv = gkm_attribute_set_bytes (attr, cdata);
     243            4 :                 g_bytes_unref (cdata);
     244            4 :                 return rv;
     245              : 
     246            2 :         case CKA_SERIAL_NUMBER:
     247            2 :                 g_return_val_if_fail (self->pv->asn1, CKR_GENERAL_ERROR);
     248            2 :                 cdata = egg_asn1x_get_element_raw (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "serialNumber", NULL));
     249            2 :                 g_return_val_if_fail (cdata, CKR_GENERAL_ERROR);
     250            2 :                 rv = gkm_attribute_set_bytes (attr, cdata);
     251            2 :                 g_bytes_unref (cdata);
     252            2 :                 return rv;
     253              : 
     254            2 :         case CKA_VALUE:
     255            2 :                 g_return_val_if_fail (self->pv->der != NULL, CKR_GENERAL_ERROR);
     256            2 :                 return gkm_attribute_set_bytes (attr, self->pv->der);
     257              : 
     258              :         /* These are only used for strange online certificates which we don't support */
     259            0 :         case CKA_URL:
     260              :         case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
     261              :         case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
     262            0 :                 return gkm_attribute_set_data (attr, "", 0);
     263              : 
     264              :         /* What in the world is this doing in the spec? */
     265            0 :         case CKA_JAVA_MIDP_SECURITY_DOMAIN:
     266            0 :                 return gkm_attribute_set_ulong (attr, 0); /* 0 = unspecified */
     267              :         };
     268              : 
     269           13 :         return GKM_OBJECT_CLASS (gkm_certificate_parent_class)->get_attribute (base, session, attr);
     270              : }
     271              : 
     272              : static GObject*
     273           36 : gkm_certificate_constructor (GType type, guint n_props, GObjectConstructParam *props)
     274              : {
     275           36 :         GkmCertificate *self = GKM_CERTIFICATE (G_OBJECT_CLASS (gkm_certificate_parent_class)->constructor(type, n_props, props));
     276           36 :         g_return_val_if_fail (self, NULL);
     277              : 
     278              : 
     279           36 :         return G_OBJECT (self);
     280              : }
     281              : 
     282              : static void
     283           36 : gkm_certificate_init (GkmCertificate *self)
     284              : {
     285           36 :         self->pv = gkm_certificate_get_instance_private (self);
     286              : 
     287           36 : }
     288              : 
     289              : static void
     290           63 : gkm_certificate_dispose (GObject *obj)
     291              : {
     292           63 :         GkmCertificate *self = GKM_CERTIFICATE (obj);
     293              : 
     294           63 :         if (self->pv->key)
     295           36 :                 g_object_unref (self->pv->key);
     296           63 :         self->pv->key = NULL;
     297              : 
     298           63 :         G_OBJECT_CLASS (gkm_certificate_parent_class)->dispose (obj);
     299           63 : }
     300              : 
     301              : static void
     302           36 : gkm_certificate_finalize (GObject *obj)
     303              : {
     304           36 :         GkmCertificate *self = GKM_CERTIFICATE (obj);
     305              : 
     306           36 :         g_assert (!self->pv->key);
     307           36 :         if (self->pv->der)
     308           36 :                 g_bytes_unref (self->pv->der);
     309           36 :         g_free (self->pv->label);
     310           36 :         egg_asn1x_destroy (self->pv->asn1);
     311              : 
     312           36 :         G_OBJECT_CLASS (gkm_certificate_parent_class)->finalize (obj);
     313           36 : }
     314              : 
     315              : static void
     316            0 : gkm_certificate_set_property (GObject *obj, guint prop_id, const GValue *value,
     317              :                               GParamSpec *pspec)
     318              : {
     319            0 :         GkmCertificate *self = GKM_CERTIFICATE (obj);
     320              : 
     321            0 :         switch (prop_id) {
     322            0 :         case PROP_LABEL:
     323            0 :                 gkm_certificate_set_label (self, g_value_get_string (value));
     324            0 :                 break;
     325            0 :         default:
     326            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     327            0 :                 break;
     328              :         }
     329            0 : }
     330              : 
     331              : static void
     332            0 : gkm_certificate_get_property (GObject *obj, guint prop_id, GValue *value,
     333              :                               GParamSpec *pspec)
     334              : {
     335            0 :         GkmCertificate *self = GKM_CERTIFICATE (obj);
     336              : 
     337            0 :         switch (prop_id) {
     338            0 :         case PROP_LABEL:
     339            0 :                 g_value_set_string (value, gkm_certificate_get_label (self));
     340            0 :                 break;
     341            0 :         case PROP_PUBLIC_KEY:
     342            0 :                 g_value_set_object (value, gkm_certificate_get_public_key (self));
     343            0 :                 break;
     344            0 :         default:
     345            0 :                 G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
     346            0 :                 break;
     347              :         }
     348            0 : }
     349              : 
     350              : static void
     351            6 : gkm_certificate_class_init (GkmCertificateClass *klass)
     352              : {
     353            6 :         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     354            6 :         GkmObjectClass *gkm_class = GKM_OBJECT_CLASS (klass);
     355              : 
     356            6 :         gobject_class->constructor = gkm_certificate_constructor;
     357            6 :         gobject_class->dispose = gkm_certificate_dispose;
     358            6 :         gobject_class->finalize = gkm_certificate_finalize;
     359            6 :         gobject_class->set_property = gkm_certificate_set_property;
     360            6 :         gobject_class->get_property = gkm_certificate_get_property;
     361              : 
     362            6 :         gkm_class->get_attribute = gkm_certificate_real_get_attribute;
     363              : 
     364            6 :         g_object_class_install_property (gobject_class, PROP_PUBLIC_KEY,
     365              :                    g_param_spec_object ("public-key", "Public Key", "Public key contained in certificate",
     366              :                                         GKM_TYPE_CERTIFICATE_KEY, G_PARAM_READABLE));
     367              : 
     368            6 :         g_object_class_install_property (gobject_class, PROP_PUBLIC_KEY,
     369              :                    g_param_spec_string ("label", "Label", "Label of the certificate",
     370              :                                         "", G_PARAM_READWRITE));
     371              : 
     372            6 :         init_quarks ();
     373            6 : }
     374              : 
     375              : static gboolean
     376           36 : gkm_certificate_real_load (GkmSerializable *base,
     377              :                            GkmSecret *login,
     378              :                            GBytes *data)
     379              : {
     380           36 :         GkmCertificate *self = GKM_CERTIFICATE (base);
     381           36 :         GNode *asn1 = NULL;
     382              :         GkmDataResult res;
     383              :         GBytes *keydata;
     384              :         gcry_sexp_t sexp;
     385              :         GkmSexp *wrapper;
     386              : 
     387           36 :         if (g_bytes_get_size (data) == 0) {
     388            0 :                 gkm_debug ("cannot load empty certificate file");
     389            0 :                 return FALSE;
     390              :         }
     391              : 
     392              :         /* Parse the ASN1 data */
     393           36 :         res = gkm_data_der_read_certificate (data, &asn1);
     394           36 :         if (res != GKM_DATA_SUCCESS) {
     395            0 :                 gkm_debug ("couldn't parse certificate data");
     396            0 :                 return FALSE;
     397              :         }
     398              : 
     399              :         /* Generate a raw public key from our certificate */
     400           36 :         keydata = egg_asn1x_encode (egg_asn1x_node (asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), NULL);
     401           36 :         g_return_val_if_fail (keydata, FALSE);
     402              : 
     403              :         /* Now create us a nice public key with that identifier */
     404           36 :         res = gkm_data_der_read_public_key_info (keydata, &sexp);
     405           36 :         g_bytes_unref (keydata);
     406              : 
     407           36 :         switch (res) {
     408              : 
     409              :         /* Create ourselves a public key with that */
     410           36 :         case GKM_DATA_SUCCESS:
     411           36 :                 wrapper = gkm_sexp_new (sexp);
     412           36 :                 if (!self->pv->key)
     413           36 :                         self->pv->key = gkm_certificate_key_new (gkm_object_get_module (GKM_OBJECT (self)),
     414           36 :                                                                  gkm_object_get_manager (GKM_OBJECT (self)),
     415              :                                                                  self);
     416           36 :                 gkm_sexp_key_set_base (GKM_SEXP_KEY (self->pv->key), wrapper);
     417           36 :                 gkm_sexp_unref (wrapper);
     418           36 :                 break;
     419              : 
     420              :         /* Unknown type of public key for this certificate, just ignore */
     421            0 :         case GKM_DATA_UNRECOGNIZED:
     422            0 :                 if (self->pv->key)
     423            0 :                         g_object_unref (self->pv->key);
     424            0 :                 self->pv->key = NULL;
     425            0 :                 break;
     426              : 
     427              :         /* Bad key, drop certificate */
     428            0 :         case GKM_DATA_FAILURE:
     429              :         case GKM_DATA_LOCKED:
     430            0 :                 g_warning ("couldn't parse certificate key data");
     431            0 :                 egg_asn1x_destroy (asn1);
     432            0 :                 return FALSE;
     433              : 
     434            0 :         default:
     435            0 :                 g_assert_not_reached ();
     436              :                 break;
     437              :         }
     438              : 
     439           36 :         g_bytes_ref (data);
     440           36 :         if (self->pv->der)
     441            0 :                 g_bytes_unref (self->pv->der);
     442           36 :         self->pv->der = data;
     443              : 
     444           36 :         egg_asn1x_destroy (self->pv->asn1);
     445           36 :         self->pv->asn1 = asn1;
     446              : 
     447           36 :         return TRUE;
     448              : }
     449              : 
     450              : static GBytes *
     451            5 : gkm_certificate_real_save (GkmSerializable *base,
     452              :                            GkmSecret *login)
     453              : {
     454            5 :         GkmCertificate *self = GKM_CERTIFICATE (base);
     455              : 
     456            5 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), FALSE);
     457              : 
     458            5 :         return g_bytes_ref (self->pv->der);
     459              : }
     460              : 
     461              : static void
     462            6 : gkm_certificate_serializable (GkmSerializableIface *iface)
     463              : {
     464            6 :         iface->extension = ".cer";
     465            6 :         iface->load = gkm_certificate_real_load;
     466            6 :         iface->save = gkm_certificate_real_save;
     467            6 : }
     468              : 
     469              : /* -----------------------------------------------------------------------------
     470              :  * PUBLIC
     471              :  */
     472              : 
     473              : gboolean
     474            0 : gkm_certificate_calc_category (GkmCertificate *self, GkmSession *session, CK_ULONG* category)
     475              : {
     476              :         GBytes *extension;
     477              :         GkmManager *manager;
     478              :         GkmDataResult res;
     479              :         gboolean is_ca;
     480              :         GkmObject *object;
     481              : 
     482            0 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), CKR_GENERAL_ERROR);
     483            0 :         g_return_val_if_fail (category, CKR_GENERAL_ERROR);
     484              : 
     485              :         /* First see if we have a private key for this certificate */
     486            0 :         manager = gkm_object_get_manager (GKM_OBJECT (self));
     487            0 :         if (manager != NULL) {
     488            0 :                 object = gkm_manager_find_related (manager, session, CKO_PRIVATE_KEY, GKM_OBJECT (self));
     489            0 :                 if (object != NULL) {
     490            0 :                         *category = 1; /* token user */
     491            0 :                         return TRUE;
     492              :                 }
     493              :         }
     494              : 
     495              :         /* Read in the Basic Constraints section */
     496            0 :         extension = gkm_certificate_get_extension (self, OID_BASIC_CONSTRAINTS, NULL);
     497            0 :         if (extension != NULL) {
     498            0 :                 res = gkm_data_der_read_basic_constraints (extension, &is_ca, NULL);
     499              : 
     500            0 :                 if (res != GKM_DATA_SUCCESS)
     501            0 :                         return FALSE;
     502              : 
     503            0 :                 if (is_ca)
     504            0 :                         *category = 2; /* authority */
     505              :                 else
     506            0 :                         *category = 3; /* other entity */
     507              : 
     508              :         } else {
     509            0 :                 *category = 0; /* unspecified */
     510              :         }
     511              : 
     512            0 :         return TRUE;
     513              : }
     514              : 
     515              : GkmCertificateKey*
     516            0 : gkm_certificate_get_public_key (GkmCertificate *self)
     517              : {
     518            0 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), NULL);
     519            0 :         return self->pv->key;
     520              : }
     521              : 
     522              : GBytes *
     523            0 : gkm_certificate_get_extension (GkmCertificate *self, GQuark oid,
     524              :                                gboolean *critical)
     525              : {
     526              :         guchar *val;
     527              :         gsize n_val;
     528              :         gint index;
     529              : 
     530            0 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), NULL);
     531            0 :         g_return_val_if_fail (self->pv->asn1, NULL);
     532            0 :         g_return_val_if_fail (oid, NULL);
     533              : 
     534            0 :         index = find_certificate_extension (self, oid);
     535            0 :         if (index <= 0)
     536            0 :                 return NULL;
     537              : 
     538              :         /* Read the critical status */
     539            0 :         if (critical) {
     540            0 :                 val = egg_asn1x_get_string_as_raw (egg_asn1x_node (self->pv->asn1, "tbsCertificate",
     541              :                                                    "extensions", index, "critical", NULL), NULL, &n_val);
     542              : 
     543              :                 /*
     544              :                  * We're pretty liberal in what we accept as critical. The goal
     545              :                  * here is not to accidentally mark as non-critical what some
     546              :                  * other x509 implementation meant to say critical.
     547              :                  */
     548            0 :                 if (!val || n_val < 1 || g_ascii_toupper (val[0]) != 'T')
     549            0 :                         *critical = FALSE;
     550              :                 else
     551            0 :                         *critical = TRUE;
     552            0 :                 g_free (val);
     553              :         }
     554              : 
     555              :         /* And the extension value */
     556            0 :         return egg_asn1x_get_string_as_bytes (egg_asn1x_node (self->pv->asn1, "tbsCertificate",
     557              :                                               "extensions", index, "extnValue", NULL));
     558              : }
     559              : 
     560              : const gchar*
     561            2 : gkm_certificate_get_label (GkmCertificate *self)
     562              : {
     563              :         gchar *label;
     564              : 
     565            2 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), "");
     566              : 
     567            2 :         if (!self->pv->label) {
     568            2 :                 g_return_val_if_fail (self->pv->asn1, "");
     569              : 
     570              :                 /* Look for the CN in the certificate */
     571            2 :                 label = egg_dn_read_part (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "subject", "rdnSequence", NULL), "cn");
     572              : 
     573              :                 /* Otherwise use the full DN */
     574            2 :                 if (!label)
     575            0 :                         label = egg_dn_read (egg_asn1x_node (self->pv->asn1, "tbsCertificate", "subject", "rdnSequence", NULL));
     576              : 
     577            2 :                 if (!label)
     578            0 :                         label = g_strdup (_("Unnamed Certificate"));
     579              : 
     580            2 :                 self->pv->label = label;
     581              : 
     582              :         }
     583              : 
     584            2 :         return self->pv->label;
     585              : }
     586              : 
     587              : void
     588            0 : gkm_certificate_set_label (GkmCertificate *self, const gchar *label)
     589              : {
     590            0 :         g_return_if_fail (GKM_IS_CERTIFICATE (self));
     591            0 :         g_free (self->pv->label);
     592            0 :         self->pv->label = g_strdup (label);
     593            0 :         g_object_notify (G_OBJECT (self), "label");
     594              : }
     595              : 
     596              : guchar*
     597            1 : gkm_certificate_hash (GkmCertificate *self, int hash_algo, gsize *n_hash)
     598              : {
     599              :         guchar *hash;
     600              : 
     601            1 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), NULL);
     602            1 :         g_return_val_if_fail (self->pv->der != NULL, NULL);
     603            1 :         g_return_val_if_fail (n_hash, NULL);
     604              : 
     605            1 :         *n_hash = gcry_md_get_algo_dlen (hash_algo);
     606            1 :         g_return_val_if_fail (*n_hash > 0, NULL);
     607              : 
     608            1 :         hash = g_malloc0 (*n_hash);
     609            1 :         gcry_md_hash_buffer (hash_algo, hash, g_bytes_get_data (self->pv->der, NULL),
     610            1 :                              g_bytes_get_size (self->pv->der));
     611              : 
     612            1 :         return hash;
     613              : }
     614              : 
     615              : gconstpointer
     616            0 : gkm_certificate_der_data (GkmCertificate *self, gsize *n_data)
     617              : {
     618            0 :         g_return_val_if_fail (GKM_IS_CERTIFICATE (self), NULL);
     619            0 :         g_return_val_if_fail (self->pv->der != NULL, NULL);
     620            0 :         g_return_val_if_fail (n_data, NULL);
     621              : 
     622            0 :         *n_data = g_bytes_get_size (self->pv->der);
     623            0 :         return g_bytes_get_data (self->pv->der, NULL);
     624              : }
     625              : 
     626              : GkmFactory*
     627          348 : gkm_certificate_get_factory (void)
     628              : {
     629              :         static CK_OBJECT_CLASS klass = CKO_CERTIFICATE;
     630              :         static CK_CERTIFICATE_TYPE type = CKC_X_509;
     631              : 
     632              :         static CK_ATTRIBUTE attributes[] = {
     633              :                 { CKA_CLASS, &klass, sizeof (klass) },
     634              :                 { CKA_CERTIFICATE_TYPE, &type, sizeof (type) },
     635              :         };
     636              : 
     637              :         static GkmFactory factory = {
     638              :                 attributes,
     639              :                 G_N_ELEMENTS (attributes),
     640              :                 factory_create_certificate
     641              :         };
     642              : 
     643          348 :         return &factory;
     644              : }
        

Generated by: LCOV version 2.0-1