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 : }
|