Branch data Line data Source code
1 : : /*
2 : : * gnome-keyring
3 : : *
4 : : * Copyright (C) 2011 Collabora Ltd.
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 <http://www.gnu.org/licenses/>.
18 : : *
19 : : * Author: Stef Walter <stefw@collabora.co.uk>
20 : : */
21 : : #include "config.h"
22 : :
23 : : #include "gcr-subject-public-key.h"
24 : : #include "gcr-types.h"
25 : :
26 : : #include "gcr/gcr-oids.h"
27 : :
28 : : #include "egg/egg-asn1x.h"
29 : : #include "egg/egg-asn1-defs.h"
30 : : #include "egg/egg-error.h"
31 : :
32 : : #include <glib/gi18n-lib.h>
33 : :
34 : : #include <gcrypt.h>
35 : :
36 : : static gboolean
37 : 93 : check_object_basics (GckBuilder *builder,
38 : : gulong *klass,
39 : : gulong *type)
40 : : {
41 [ - + ]: 93 : g_assert (klass != NULL);
42 [ - + ]: 93 : g_assert (type != NULL);
43 : :
44 [ + + ]: 93 : if (!gck_builder_find_ulong (builder, CKA_CLASS, klass))
45 : 38 : return FALSE;
46 : :
47 [ + + + + ]: 55 : if (*klass == CKO_PUBLIC_KEY || *klass == CKO_PRIVATE_KEY)
48 : 36 : return gck_builder_find_ulong (builder, CKA_KEY_TYPE, type);
49 : :
50 [ + - ]: 19 : else if (*klass == CKO_CERTIFICATE)
51 : 19 : return gck_builder_find_ulong (builder, CKA_CERTIFICATE_TYPE, type);
52 : :
53 : 0 : *type = GCK_INVALID;
54 : 0 : return FALSE;
55 : : }
56 : :
57 : : static gboolean
58 : 28 : load_object_basics (GckObject *object,
59 : : GckBuilder *builder,
60 : : GCancellable *cancellable,
61 : : gulong *klass,
62 : : gulong *type,
63 : : GError **lerror)
64 : : {
65 : 28 : gulong attr_types[] = { CKA_CLASS, CKA_KEY_TYPE, CKA_CERTIFICATE_TYPE };
66 : : GckAttributes *attrs;
67 : 28 : GError *error = NULL;
68 : :
69 [ - + ]: 28 : g_assert (klass != NULL);
70 [ - + ]: 28 : g_assert (type != NULL);
71 : :
72 [ - + ]: 28 : if (check_object_basics (builder, klass, type)) {
73 : 0 : g_debug ("already loaded: class = %lu, type = %lu", *klass, *type);
74 : 0 : return TRUE;
75 : : }
76 : :
77 : 28 : attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
78 : : cancellable, &error);
79 [ + + ]: 28 : if (error != NULL) {
80 : 1 : g_debug ("couldn't load: %s", error->message);
81 : 1 : g_propagate_error (lerror, error);
82 : 1 : return FALSE;
83 : : }
84 : :
85 : 27 : gck_builder_set_all (builder, attrs);
86 : 27 : gck_attributes_unref (attrs);
87 : :
88 [ - + ]: 27 : if (!check_object_basics (builder, klass, type))
89 : 0 : return FALSE;
90 : :
91 : 27 : g_debug ("loaded: class = %lu, type = %lu", *klass, *type);
92 : 27 : return TRUE;
93 : : }
94 : :
95 : : static gboolean
96 : 19 : check_x509_attributes (GckBuilder *builder)
97 : : {
98 : 19 : const GckAttribute *value = gck_builder_find (builder, CKA_VALUE);
99 [ + + + - ]: 19 : return (value && !gck_attribute_is_invalid (value));
100 : : }
101 : :
102 : : static gboolean
103 : 9 : load_x509_attributes (GckObject *object,
104 : : GckBuilder *builder,
105 : : GCancellable *cancellable,
106 : : GError **lerror)
107 : : {
108 : 9 : gulong attr_types[] = { CKA_VALUE };
109 : : GckAttributes *attrs;
110 : 9 : GError *error = NULL;
111 : :
112 [ + + ]: 9 : if (check_x509_attributes (builder)) {
113 : 3 : g_debug ("already loaded");
114 : 3 : return TRUE;
115 : : }
116 : :
117 : 6 : attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
118 : : cancellable, &error);
119 [ - + ]: 6 : if (error != NULL) {
120 : 0 : g_debug ("couldn't load: %s", error->message);
121 : 0 : g_propagate_error (lerror, error);
122 : 0 : return FALSE;
123 : : }
124 : :
125 : 6 : gck_builder_set_all (builder, attrs);
126 : 6 : gck_attributes_unref (attrs);
127 : :
128 : 6 : return check_x509_attributes (builder);
129 : : }
130 : :
131 : : static gboolean
132 : 14 : check_rsa_attributes (GckBuilder *builder)
133 : : {
134 : : const GckAttribute *modulus;
135 : : const GckAttribute *exponent;
136 : :
137 : 14 : modulus = gck_builder_find (builder, CKA_MODULUS);
138 : 14 : exponent = gck_builder_find (builder, CKA_PUBLIC_EXPONENT);
139 : :
140 [ + - + + ]: 9 : return (modulus && !gck_attribute_is_invalid (modulus) &&
141 [ + + + - ]: 23 : exponent && !gck_attribute_is_invalid (exponent));
142 : : }
143 : :
144 : : static gboolean
145 : 6 : load_rsa_attributes (GckObject *object,
146 : : GckBuilder *builder,
147 : : GCancellable *cancellable,
148 : : GError **lerror)
149 : : {
150 : 6 : gulong attr_types[] = { CKA_MODULUS, CKA_PUBLIC_EXPONENT };
151 : : GckAttributes *attrs;
152 : 6 : GError *error = NULL;
153 : :
154 [ - + ]: 6 : if (check_rsa_attributes (builder)) {
155 : 0 : g_debug ("rsa attributes already loaded");
156 : 0 : return TRUE;
157 : : }
158 : :
159 : 6 : attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
160 : : cancellable, &error);
161 [ - + ]: 6 : if (error != NULL) {
162 : 0 : g_debug ("couldn't load rsa attributes: %s", error->message);
163 : 0 : g_propagate_error (lerror, error);
164 : 0 : return FALSE;
165 : : }
166 : :
167 : 6 : gck_builder_set_all (builder, attrs);
168 : 6 : gck_attributes_unref (attrs);
169 : :
170 : 6 : return check_rsa_attributes (builder);
171 : : }
172 : :
173 : : static GckObject *
174 : 6 : lookup_public_key (GckObject *object,
175 : : GCancellable *cancellable,
176 : : GError **lerror)
177 : : {
178 : 6 : GckBuilder builder = GCK_BUILDER_INIT;
179 : 6 : gulong attr_types[] = { CKA_ID };
180 : : GckAttributes *attrs;
181 : 6 : GError *error = NULL;
182 : : GckSession *session;
183 : : GckObject *result;
184 : : const GckAttribute *id;
185 : : GList *objects;
186 : :
187 : 6 : attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
188 : : cancellable, &error);
189 [ - + ]: 6 : if (error != NULL) {
190 : 0 : g_debug ("couldn't load private key id: %s", error->message);
191 : 0 : g_propagate_error (lerror, error);
192 : 0 : return NULL;
193 : : }
194 : :
195 : 6 : id = gck_attributes_find (attrs, CKA_ID);
196 [ + - - + ]: 6 : if (id == NULL || gck_attribute_is_invalid (id)) {
197 : 0 : gck_attributes_unref (attrs);
198 : 0 : g_debug ("couldn't load private key id");
199 : 0 : g_set_error_literal (lerror, GCK_ERROR, CKR_ATTRIBUTE_TYPE_INVALID,
200 : : gck_message_from_rv (CKR_ATTRIBUTE_TYPE_INVALID));
201 : 0 : return NULL;
202 : : }
203 : :
204 : 6 : gck_builder_add_ulong (&builder, CKA_CLASS, CKO_PUBLIC_KEY);
205 : 6 : gck_builder_add_attribute (&builder, id);
206 : 6 : gck_attributes_unref (attrs);
207 : :
208 : 6 : session = gck_object_get_session (object);
209 : 6 : attrs = gck_builder_end (&builder);
210 : 6 : objects = gck_session_find_objects (session, attrs, cancellable, &error);
211 : 6 : gck_attributes_unref (attrs);
212 : 6 : g_object_unref (session);
213 : :
214 [ - + ]: 6 : if (error != NULL) {
215 : 0 : g_debug ("couldn't lookup public key: %s", error->message);
216 : 0 : g_propagate_error (lerror, error);
217 : 0 : return NULL;
218 : : }
219 : :
220 [ - + ]: 6 : if (!objects)
221 : 0 : return NULL;
222 : :
223 : 6 : result = g_object_ref (objects->data);
224 [ + - ]: 6 : g_clear_list (&objects, g_object_unref);
225 : :
226 : 6 : return result;
227 : : }
228 : :
229 : : static gboolean
230 : 14 : check_dsa_attributes (GckBuilder *builder)
231 : : {
232 : : const GckAttribute *prime;
233 : : const GckAttribute *subprime;
234 : : const GckAttribute *base;
235 : : const GckAttribute *value;
236 : :
237 : 14 : prime = gck_builder_find (builder, CKA_PRIME);
238 : 14 : subprime = gck_builder_find (builder, CKA_SUBPRIME);
239 : 14 : base = gck_builder_find (builder, CKA_BASE);
240 : 14 : value = gck_builder_find (builder, CKA_VALUE);
241 : :
242 [ + - + + ]: 9 : return (prime && !gck_attribute_is_invalid (prime) &&
243 [ + - + - ]: 8 : subprime && !gck_attribute_is_invalid (subprime) &&
244 [ + - + - ]: 8 : base && !gck_attribute_is_invalid (base) &&
245 [ + + + - ]: 23 : value && !gck_attribute_is_invalid (value));
246 : : }
247 : :
248 : : static gboolean
249 : 6 : load_dsa_attributes (GckObject *object,
250 : : GckBuilder *builder,
251 : : GCancellable *cancellable,
252 : : GError **lerror)
253 : : {
254 : 6 : gulong attr_types[] = { CKA_PRIME, CKA_SUBPRIME, CKA_BASE, CKA_VALUE };
255 : 6 : GError *error = NULL;
256 : : GckAttributes *loaded;
257 : : GckObject *publi;
258 : : gulong klass;
259 : :
260 [ - + ]: 6 : if (check_dsa_attributes (builder))
261 : 0 : return TRUE;
262 : :
263 [ - + ]: 6 : if (!gck_builder_find_ulong (builder, CKA_CLASS, &klass))
264 : 0 : g_return_val_if_reached (FALSE);
265 : :
266 : : /* If it's a private key, find the public one */
267 [ + + ]: 6 : if (klass == CKO_PRIVATE_KEY)
268 : 3 : publi = lookup_public_key (object, cancellable, lerror);
269 : :
270 : : else
271 : 3 : publi = g_object_ref (object);
272 : :
273 [ - + ]: 6 : if (!publi)
274 : 0 : return FALSE;
275 : :
276 : 6 : loaded = gck_object_cache_lookup (publi, attr_types, G_N_ELEMENTS (attr_types),
277 : : cancellable, &error);
278 : 6 : g_object_unref (publi);
279 : :
280 [ - + ]: 6 : if (error != NULL) {
281 : 0 : g_debug ("couldn't load rsa attributes: %s", error->message);
282 : 0 : g_propagate_error (lerror, error);
283 : 0 : return FALSE;
284 : : }
285 : :
286 : : /* We've made sure to load info from the public key, so change class */
287 : 6 : gck_builder_set_ulong (builder, CKA_CLASS, CKO_PUBLIC_KEY);
288 : :
289 : 6 : gck_builder_set_all (builder, loaded);
290 : 6 : gck_attributes_unref (loaded);
291 : :
292 : 6 : return check_dsa_attributes (builder);
293 : : }
294 : :
295 : : static gboolean
296 : 14 : check_ec_attributes (GckBuilder *builder)
297 : : {
298 : : const GckAttribute *ec_params;
299 : : const GckAttribute *ec_point;
300 : :
301 : 14 : ec_params = gck_builder_find (builder, CKA_EC_PARAMS);
302 : 14 : ec_point = gck_builder_find (builder, CKA_EC_POINT);
303 : :
304 [ + - + + ]: 9 : return (ec_params && !gck_attribute_is_invalid (ec_params) &&
305 [ + + + - ]: 23 : ec_point && !gck_attribute_is_invalid (ec_point));
306 : : }
307 : :
308 : :
309 : : static gboolean
310 : 6 : load_ec_attributes (GckObject *object,
311 : : GckBuilder *builder,
312 : : GCancellable *cancellable,
313 : : GError **lerror)
314 : : {
315 : 6 : gulong attr_types[] = { CKA_EC_PARAMS, CKA_EC_POINT };
316 : : GckAttributes *attrs;
317 : 6 : GError *error = NULL;
318 : : GckObject *publi;
319 : : gulong klass;
320 : :
321 [ - + ]: 6 : if (check_ec_attributes (builder)) {
322 : 0 : g_debug ("ec attributes already loaded");
323 : 0 : return TRUE;
324 : : }
325 : :
326 [ - + ]: 6 : if (!gck_builder_find_ulong (builder, CKA_CLASS, &klass))
327 : 0 : g_return_val_if_reached (FALSE);
328 : :
329 : : /* If it's a private key, find the public one */
330 [ + + ]: 6 : if (klass == CKO_PRIVATE_KEY)
331 : 3 : publi = lookup_public_key (object, cancellable, lerror);
332 : :
333 : : else
334 : 3 : publi = g_object_ref (object);
335 : :
336 [ - + ]: 6 : if (!publi)
337 : 0 : return FALSE;
338 : :
339 : 6 : attrs = gck_object_cache_lookup (publi, attr_types, G_N_ELEMENTS (attr_types),
340 : : cancellable, &error);
341 : 6 : g_object_unref (publi);
342 : :
343 [ - + ]: 6 : if (error != NULL) {
344 : 0 : g_debug ("couldn't load ec attributes: %s", error->message);
345 : 0 : g_propagate_error (lerror, error);
346 : 0 : return FALSE;
347 : : }
348 : :
349 : 6 : gck_builder_set_all (builder, attrs);
350 : 6 : gck_attributes_unref (attrs);
351 : :
352 : 6 : return check_ec_attributes (builder);
353 : : }
354 : :
355 : : static gboolean
356 : 28 : load_attributes (GckObject *object,
357 : : GckBuilder *builder,
358 : : GCancellable *cancellable,
359 : : GError **lerror)
360 : : {
361 : 28 : gboolean ret = FALSE;
362 : : gulong klass;
363 : : gulong type;
364 : :
365 [ + + ]: 28 : if (!load_object_basics (object, builder, cancellable,
366 : : &klass, &type, lerror))
367 : 1 : return FALSE;
368 : :
369 [ + + - ]: 27 : switch (klass) {
370 : :
371 : 9 : case CKO_CERTIFICATE:
372 [ + - ]: 9 : switch (type) {
373 : 9 : case CKC_X_509:
374 : 9 : ret = load_x509_attributes (object, builder, cancellable, lerror);
375 : 9 : break;
376 : 0 : default:
377 : 0 : g_debug ("unsupported certificate type: %lu", type);
378 : 0 : break;
379 : : }
380 : 9 : break;
381 : :
382 : 18 : case CKO_PUBLIC_KEY:
383 : : case CKO_PRIVATE_KEY:
384 [ + + + - ]: 18 : switch (type) {
385 : 6 : case CKK_RSA:
386 : 6 : ret = load_rsa_attributes (object, builder, cancellable, lerror);
387 : 6 : break;
388 : 6 : case CKK_DSA:
389 : 6 : ret = load_dsa_attributes (object, builder, cancellable, lerror);
390 : 6 : break;
391 : 6 : case CKK_EC:
392 : 6 : ret = load_ec_attributes (object, builder, cancellable, lerror);
393 : 6 : break;
394 : 0 : default:
395 : 0 : g_debug ("unsupported key type: %lu", type);
396 : 0 : break;
397 : : }
398 : 18 : break;
399 : :
400 : 0 : default:
401 : 0 : g_debug ("unsupported class: %lu", type);
402 : 0 : break;
403 : : }
404 : :
405 [ - + - - : 27 : if (ret == FALSE && lerror != NULL && *lerror == NULL) {
- - ]
406 : 0 : g_set_error_literal (lerror, GCR_DATA_ERROR, GCR_ERROR_UNRECOGNIZED,
407 : : _("Unrecognized or unavailable attributes for key"));
408 : : }
409 : :
410 : 27 : return ret;
411 : : }
412 : :
413 : : static gboolean
414 : 38 : check_attributes (GckBuilder *builder)
415 : : {
416 : : gulong klass;
417 : : gulong type;
418 : :
419 [ + + ]: 38 : if (!check_object_basics (builder, &klass, &type))
420 : 28 : return FALSE;
421 : :
422 [ + + - ]: 10 : switch (klass) {
423 : :
424 : 4 : case CKO_CERTIFICATE:
425 [ + - ]: 4 : switch (type) {
426 : 4 : case CKC_X_509:
427 : 4 : return check_x509_attributes (builder);
428 : 0 : default:
429 : 0 : return FALSE;
430 : : }
431 : :
432 : 6 : case CKO_PUBLIC_KEY:
433 : : case CKO_PRIVATE_KEY:
434 [ + + + - ]: 6 : switch (type) {
435 : 2 : case CKK_RSA:
436 : 2 : return check_rsa_attributes (builder);
437 : 2 : case CKK_DSA:
438 : 2 : return check_dsa_attributes (builder);
439 : 2 : case CKK_EC:
440 : 2 : return check_ec_attributes (builder);
441 : 0 : default:
442 : 0 : return FALSE;
443 : : }
444 : :
445 : 0 : default:
446 : 0 : return FALSE;
447 : : }
448 : : }
449 : :
450 : : static void
451 : 38 : lookup_attributes (GckObject *object,
452 : : GckBuilder *builder)
453 : : {
454 : : GckObjectCache *oakey;
455 : : GckAttributes *attrs;
456 : :
457 [ + + ]: 38 : if (GCK_IS_OBJECT_CACHE (object)) {
458 : 20 : oakey = GCK_OBJECT_CACHE (object);
459 : 20 : attrs = gck_object_cache_get_attributes (oakey);
460 [ + + ]: 20 : if (attrs != NULL) {
461 : 19 : gck_builder_add_all (builder, attrs);
462 : 19 : gck_attributes_unref (attrs);
463 : : }
464 : : }
465 : 38 : }
466 : :
467 : : GNode *
468 : 29 : _gcr_subject_public_key_load (GckObject *key,
469 : : GCancellable *cancellable,
470 : : GError **error)
471 : : {
472 : 29 : GckBuilder builder = GCK_BUILDER_INIT;
473 : : GckAttributes *attributes;
474 : : GNode *asn;
475 : :
476 [ - + ]: 29 : g_return_val_if_fail (GCK_IS_OBJECT (key), NULL);
477 [ - + - - : 29 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
- - - - -
- ]
478 [ + - - + ]: 29 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
479 : :
480 : 29 : lookup_attributes (key, &builder);
481 : :
482 [ + + ]: 29 : if (!check_attributes (&builder)) {
483 [ + + ]: 19 : if (!load_attributes (key, &builder, cancellable, error)) {
484 : 1 : gck_builder_clear (&builder);
485 : 1 : return NULL;
486 : : }
487 : : }
488 : :
489 : 28 : attributes = gck_builder_end (&builder);
490 : 28 : asn = _gcr_subject_public_key_for_attributes (attributes);
491 [ + + ]: 28 : if (asn == NULL) {
492 : 1 : g_set_error_literal (error, GCK_ERROR, CKR_TEMPLATE_INCONSISTENT,
493 : : _("Couldn’t build public key"));
494 : : }
495 : :
496 : 28 : gck_attributes_unref (attributes);
497 : 28 : return asn;
498 : : }
499 : :
500 : : typedef struct {
501 : : GckObject *object;
502 : : GckBuilder builder;
503 : : } LoadClosure;
504 : :
505 : : static void
506 : 9 : load_closure_free (gpointer data)
507 : : {
508 : 9 : LoadClosure *closure = data;
509 : 9 : g_object_unref (closure->object);
510 : 9 : gck_builder_clear (&closure->builder);
511 : 9 : g_slice_free (LoadClosure, closure);
512 : 9 : }
513 : :
514 : : static void
515 : 9 : thread_key_attributes (GTask *task, gpointer src_object, gpointer task_data,
516 : : GCancellable *cancellable)
517 : : {
518 : 9 : LoadClosure *closure = task_data;
519 : 9 : GError *error = NULL;
520 : :
521 [ + - ]: 9 : if (load_attributes (closure->object, &closure->builder, cancellable, &error))
522 : 9 : g_task_return_boolean (task, TRUE);
523 : : else
524 : 0 : g_task_return_error (task, g_steal_pointer (&error));
525 : 9 : }
526 : :
527 : : void
528 : 9 : _gcr_subject_public_key_load_async (GckObject *key,
529 : : GCancellable *cancellable,
530 : : GAsyncReadyCallback callback,
531 : : gpointer user_data)
532 : : {
533 : : GTask *task;
534 : : LoadClosure *closure;
535 : :
536 [ - + ]: 9 : g_return_if_fail (GCK_IS_OBJECT (key));
537 [ - + - - : 9 : g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
- - - - -
- ]
538 : :
539 : 9 : task = g_task_new (NULL, cancellable, callback, user_data);
540 [ + - ]: 9 : g_task_set_source_tag (task, _gcr_subject_public_key_load_async);
541 : :
542 : 9 : closure = g_slice_new0 (LoadClosure);
543 : 9 : closure->object = g_object_ref (key);
544 : 9 : lookup_attributes (key, &closure->builder);
545 : 9 : g_task_set_task_data (task, closure, load_closure_free);
546 : :
547 [ - + ]: 9 : if (check_attributes (&closure->builder)) {
548 : 0 : g_task_return_boolean (task, TRUE);
549 [ # # ]: 0 : g_clear_object (&task);
550 : 0 : return;
551 : : }
552 : :
553 : 9 : g_task_run_in_thread (task, thread_key_attributes);
554 [ + - ]: 9 : g_clear_object (&task);
555 : : }
556 : :
557 : : GNode *
558 : 9 : _gcr_subject_public_key_load_finish (GAsyncResult *result,
559 : : GError **error)
560 : : {
561 : : GckAttributes *attributes;
562 : : LoadClosure *closure;
563 : : GNode *asn;
564 : :
565 [ + - - + ]: 9 : g_return_val_if_fail (error == NULL || *error == NULL, NULL);
566 [ - + ]: 9 : g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
567 : :
568 [ - + ]: 9 : if (!g_task_propagate_boolean (G_TASK (result), error))
569 : 0 : return NULL;
570 : :
571 : 9 : closure = g_task_get_task_data (G_TASK (result));
572 : 9 : attributes = gck_builder_end (&closure->builder);
573 : 9 : asn = _gcr_subject_public_key_for_attributes (attributes);
574 [ - + ]: 9 : if (asn == NULL) {
575 : 0 : g_set_error_literal (error, GCK_ERROR, CKR_TEMPLATE_INCONSISTENT,
576 : : _("Couldn’t build public key"));
577 : : }
578 : :
579 : 9 : gck_attributes_unref (attributes);
580 : 9 : return asn;
581 : : }
582 : :
583 : : static gboolean
584 : 13 : rsa_subject_public_key_from_attributes (GckAttributes *attrs,
585 : : GNode *info_asn)
586 : : {
587 : : const GckAttribute *modulus;
588 : : const GckAttribute *exponent;
589 : : GNode *key_asn;
590 : : GNode *params_asn;
591 : : GBytes *key;
592 : : GBytes *usg;
593 : :
594 : 13 : modulus = gck_attributes_find (attrs, CKA_MODULUS);
595 : 13 : exponent = gck_attributes_find (attrs, CKA_PUBLIC_EXPONENT);
596 [ + - + - : 13 : if (modulus == NULL || gck_attribute_is_invalid (modulus) ||
+ - ]
597 [ - + ]: 13 : exponent == NULL || gck_attribute_is_invalid (exponent))
598 : 0 : return FALSE;
599 : :
600 : 13 : key_asn = egg_asn1x_create (pk_asn1_tab, "RSAPublicKey");
601 [ - + ]: 13 : g_return_val_if_fail (key_asn, FALSE);
602 : :
603 : 13 : params_asn = egg_asn1x_create (pk_asn1_tab, "RSAParameters");
604 [ - + ]: 13 : g_return_val_if_fail (params_asn, FALSE);
605 : :
606 : 13 : usg = g_bytes_new_with_free_func (modulus->value, modulus->length,
607 : : gck_attributes_unref,
608 : 13 : gck_attributes_ref (attrs));
609 : 13 : egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "modulus", NULL), usg);
610 : 13 : g_bytes_unref (usg);
611 : :
612 : 13 : usg = g_bytes_new_with_free_func (exponent->value, exponent->length,
613 : : gck_attributes_unref,
614 : 13 : gck_attributes_ref (attrs));
615 : 13 : egg_asn1x_set_integer_as_usg (egg_asn1x_node (key_asn, "publicExponent", NULL), usg);
616 : 13 : g_bytes_unref (usg);
617 : :
618 : 13 : key = egg_asn1x_encode (key_asn, NULL);
619 : 13 : egg_asn1x_destroy (key_asn);
620 : :
621 : 13 : egg_asn1x_set_null (params_asn);
622 : :
623 : 13 : egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
624 : 13 : key, g_bytes_get_size (key) * 8);
625 : :
626 : 13 : egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), GCR_OID_PKIX1_RSA);
627 : 13 : egg_asn1x_set_any_from (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params_asn);
628 : :
629 : 13 : egg_asn1x_destroy (params_asn);
630 : 13 : g_bytes_unref (key);
631 : 13 : return TRUE;
632 : : }
633 : :
634 : : static gboolean
635 : 4 : dsa_subject_public_key_from_private (GNode *key_asn,
636 : : const GckAttribute *ap,
637 : : const GckAttribute *aq,
638 : : const GckAttribute *ag,
639 : : const GckAttribute *ax)
640 : : {
641 : : gcry_mpi_t mp, mq, mg, mx, my;
642 : : size_t n_buffer;
643 : : gcry_error_t gcry;
644 : : unsigned char *buffer;
645 : :
646 : 4 : gcry = gcry_mpi_scan (&mp, GCRYMPI_FMT_USG, ap->value, ap->length, NULL);
647 [ - + ]: 4 : g_return_val_if_fail (gcry == 0, FALSE);
648 : :
649 : 4 : gcry = gcry_mpi_scan (&mq, GCRYMPI_FMT_USG, aq->value, aq->length, NULL);
650 [ - + ]: 4 : g_return_val_if_fail (gcry == 0, FALSE);
651 : :
652 : 4 : gcry = gcry_mpi_scan (&mg, GCRYMPI_FMT_USG, ag->value, ag->length, NULL);
653 [ - + ]: 4 : g_return_val_if_fail (gcry == 0, FALSE);
654 : :
655 : 4 : gcry = gcry_mpi_scan (&mx, GCRYMPI_FMT_USG, ax->value, ax->length, NULL);
656 [ - + ]: 4 : g_return_val_if_fail (gcry == 0, FALSE);
657 : :
658 : : /* Calculate the public part from the private */
659 : 4 : my = gcry_mpi_snew (gcry_mpi_get_nbits (mx));
660 [ - + ]: 4 : g_return_val_if_fail (my, FALSE);
661 : 4 : gcry_mpi_powm (my, mg, mx, mp);
662 : :
663 : 4 : gcry = gcry_mpi_aprint (GCRYMPI_FMT_STD, &buffer, &n_buffer, my);
664 [ - + ]: 4 : g_return_val_if_fail (gcry == 0, FALSE);
665 : 4 : egg_asn1x_take_integer_as_raw (key_asn, g_bytes_new_with_free_func (buffer, n_buffer,
666 : : gcry_free, buffer));
667 : :
668 : 4 : gcry_mpi_release (mp);
669 : 4 : gcry_mpi_release (mq);
670 : 4 : gcry_mpi_release (mg);
671 : 4 : gcry_mpi_release (mx);
672 : 4 : gcry_mpi_release (my);
673 : :
674 : 4 : return TRUE;
675 : : }
676 : :
677 : : static gboolean
678 : 13 : dsa_subject_public_key_from_attributes (GckAttributes *attrs,
679 : : gulong klass,
680 : : GNode *info_asn)
681 : : {
682 : : const GckAttribute *value, *g, *q, *p;
683 : : GNode *key_asn, *params_asn;
684 : : GBytes *key;
685 : :
686 : 13 : p = gck_attributes_find (attrs, CKA_PRIME);
687 : 13 : q = gck_attributes_find (attrs, CKA_SUBPRIME);
688 : 13 : g = gck_attributes_find (attrs, CKA_BASE);
689 : 13 : value = gck_attributes_find (attrs, CKA_VALUE);
690 : :
691 [ + - + - : 13 : if (p == NULL || gck_attribute_is_invalid (p) ||
+ - ]
692 [ + - + - ]: 13 : q == NULL || gck_attribute_is_invalid (q) ||
693 [ + - + - ]: 13 : g == NULL || gck_attribute_is_invalid (g) ||
694 [ - + ]: 13 : value == NULL || gck_attribute_is_invalid (value))
695 : 0 : return FALSE;
696 : :
697 : 13 : key_asn = egg_asn1x_create (pk_asn1_tab, "DSAPublicPart");
698 [ - + ]: 13 : g_return_val_if_fail (key_asn, FALSE);
699 : :
700 : 13 : params_asn = egg_asn1x_create (pk_asn1_tab, "DSAParameters");
701 [ - + ]: 13 : g_return_val_if_fail (params_asn, FALSE);
702 : :
703 : 13 : egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "p", NULL),
704 : 13 : g_bytes_new_with_free_func (p->value, p->length,
705 : : gck_attributes_unref,
706 : 13 : gck_attributes_ref (attrs)));
707 : 13 : egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "q", NULL),
708 : 13 : g_bytes_new_with_free_func (q->value, q->length,
709 : : gck_attributes_unref,
710 : 13 : gck_attributes_ref (attrs)));
711 : 13 : egg_asn1x_take_integer_as_usg (egg_asn1x_node (params_asn, "g", NULL),
712 : 13 : g_bytes_new_with_free_func (g->value, g->length,
713 : : gck_attributes_unref,
714 : 13 : gck_attributes_ref (attrs)));
715 : :
716 : : /* Are these attributes for a public or private key? */
717 [ + + ]: 13 : if (klass == CKO_PRIVATE_KEY) {
718 : :
719 : : /* We need to calculate the public from the private key */
720 [ - + ]: 4 : if (!dsa_subject_public_key_from_private (key_asn, p, q, g, value))
721 : 0 : g_return_val_if_reached (FALSE);
722 : :
723 [ + - ]: 9 : } else if (klass == CKO_PUBLIC_KEY) {
724 : 9 : egg_asn1x_take_integer_as_usg (key_asn,
725 : 9 : g_bytes_new_with_free_func (value->value, value->length,
726 : : gck_attributes_unref,
727 : 9 : gck_attributes_ref (attrs)));
728 : : } else {
729 : 0 : g_assert_not_reached ();
730 : : }
731 : :
732 : 13 : key = egg_asn1x_encode (key_asn, NULL);
733 : 13 : egg_asn1x_destroy (key_asn);
734 : :
735 : 13 : egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
736 : 13 : key, g_bytes_get_size (key) * 8);
737 : 13 : egg_asn1x_set_any_from (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params_asn);
738 : :
739 : 13 : egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), GCR_OID_PKIX1_DSA);
740 : :
741 : 13 : g_bytes_unref (key);
742 : 13 : egg_asn1x_destroy (params_asn);
743 : 13 : return TRUE;
744 : : }
745 : :
746 : : static gboolean
747 : 12 : ec_subject_public_key_from_attributes (GckAttributes *attrs,
748 : : gulong klass,
749 : : GNode *info_asn)
750 : : {
751 : : const GckAttribute *ec_params, *ec_point;
752 : : GNode *params_asn, *point_asn;
753 : : GBytes *bytes, *key_bytes;
754 : :
755 : 12 : ec_params = gck_attributes_find (attrs, CKA_EC_PARAMS);
756 : 12 : ec_point = gck_attributes_find (attrs, CKA_EC_POINT);
757 : :
758 [ + - + - : 12 : if (ec_params == NULL || gck_attribute_is_invalid (ec_params) ||
+ - ]
759 [ - + ]: 12 : ec_point == NULL || gck_attribute_is_invalid (ec_point))
760 : 0 : return FALSE;
761 : :
762 : 12 : bytes = g_bytes_new_with_free_func (ec_params->value, ec_params->length,
763 : 12 : gck_attributes_unref, gck_attributes_ref (attrs));
764 : 12 : params_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECParameters", bytes);
765 : 12 : g_bytes_unref (bytes);
766 : :
767 [ - + ]: 12 : if (params_asn == NULL)
768 : 0 : return FALSE;
769 : :
770 : 12 : bytes = g_bytes_new_with_free_func (ec_point->value, ec_point->length,
771 : 12 : gck_attributes_unref, gck_attributes_ref (attrs));
772 : 12 : point_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPoint", bytes);
773 : 12 : g_bytes_unref (bytes);
774 : :
775 [ - + ]: 12 : if (point_asn == NULL) {
776 : 0 : egg_asn1x_destroy (params_asn);
777 : 0 : return FALSE;
778 : : }
779 : 12 : key_bytes = egg_asn1x_get_string_as_bytes (point_asn);
780 : 12 : egg_asn1x_destroy (point_asn);
781 [ - + ]: 12 : if (key_bytes == NULL) {
782 : 0 : egg_asn1x_destroy (params_asn);
783 : 0 : return FALSE;
784 : : }
785 : :
786 : 12 : egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
787 : 12 : key_bytes, g_bytes_get_size (key_bytes) * 8);
788 : 12 : egg_asn1x_set_any_from (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params_asn);
789 : :
790 : 12 : egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL), GCR_OID_PKIX1_EC);
791 : :
792 : 12 : g_bytes_unref (key_bytes);
793 : 12 : egg_asn1x_destroy (params_asn);
794 : 12 : return TRUE;
795 : : }
796 : :
797 : : static GNode *
798 : 21 : cert_subject_public_key_from_attributes (GckAttributes *attributes)
799 : : {
800 : : const GckAttribute *attr;
801 : : GBytes *bytes;
802 : : GNode *cert;
803 : : GNode *asn;
804 : :
805 : 21 : attr = gck_attributes_find (attributes, CKA_VALUE);
806 [ + - - + ]: 21 : if (attr == NULL || gck_attribute_is_invalid (attr)) {
807 : 0 : g_debug ("no value attribute for certificate");
808 : 0 : return NULL;
809 : : }
810 : :
811 : 21 : bytes = g_bytes_new_with_free_func (attr->value, attr->length,
812 : : gck_attributes_unref,
813 : 21 : gck_attributes_ref (attributes));
814 : 21 : cert = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", bytes);
815 : 21 : g_bytes_unref (bytes);
816 : :
817 [ + + ]: 21 : if (cert == NULL) {
818 : 1 : g_debug ("couldn't parse certificate value");
819 : 1 : return NULL;
820 : : }
821 : :
822 : 20 : asn = egg_asn1x_node (cert, "tbsCertificate", "subjectPublicKeyInfo", NULL);
823 [ - + ]: 20 : g_return_val_if_fail (asn != NULL, NULL);
824 : :
825 : : /* Remove the subject public key out of the certificate */
826 : 20 : g_node_unlink (asn);
827 : 20 : egg_asn1x_destroy (cert);
828 : :
829 : 20 : return asn;
830 : : }
831 : :
832 : : GNode *
833 : 59 : _gcr_subject_public_key_for_attributes (GckAttributes *attributes)
834 : : {
835 : 59 : gboolean ret = FALSE;
836 : : gulong key_type;
837 : : gulong klass;
838 : 59 : GNode *asn = NULL;
839 : :
840 [ - + ]: 59 : if (!gck_attributes_find_ulong (attributes, CKA_CLASS, &klass)) {
841 : 0 : g_debug ("no class in attributes");
842 : 0 : return NULL;
843 : : }
844 : :
845 [ + + ]: 59 : if (klass == CKO_CERTIFICATE) {
846 : 21 : return cert_subject_public_key_from_attributes (attributes);
847 : :
848 [ + + + - ]: 38 : } else if (klass == CKO_PUBLIC_KEY || klass == CKO_PRIVATE_KEY) {
849 [ - + ]: 38 : if (!gck_attributes_find_ulong (attributes, CKA_KEY_TYPE, &key_type)) {
850 : 0 : g_debug ("no key type in attributes");
851 : 0 : return NULL;
852 : : }
853 : :
854 : 38 : asn = egg_asn1x_create (pkix_asn1_tab, "SubjectPublicKeyInfo");
855 [ - + ]: 38 : g_return_val_if_fail (asn, NULL);
856 : :
857 [ + + ]: 38 : if (key_type == CKK_RSA) {
858 : 13 : ret = rsa_subject_public_key_from_attributes (attributes, asn);
859 : :
860 [ + + ]: 25 : } else if (key_type == CKK_DSA) {
861 : 13 : ret = dsa_subject_public_key_from_attributes (attributes, klass, asn);
862 : :
863 [ + - ]: 12 : } else if (key_type == CKK_ECDSA) {
864 : 12 : ret = ec_subject_public_key_from_attributes (attributes, klass, asn);
865 : :
866 : : } else {
867 : 0 : g_debug ("unsupported key type: %lu", key_type);
868 : 0 : ret = FALSE;
869 : : }
870 : :
871 : :
872 [ - + ]: 38 : if (ret == FALSE) {
873 : 0 : egg_asn1x_destroy (asn);
874 : 0 : asn = NULL;
875 : : }
876 : : }
877 : :
878 : 38 : return asn;
879 : : }
880 : :
881 : : static guint
882 : 4 : calculate_rsa_key_size (GBytes *data)
883 : : {
884 : : GNode *asn;
885 : : GBytes *content;
886 : : guint key_size;
887 : :
888 : 4 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPublicKey", data);
889 [ - + ]: 4 : g_return_val_if_fail (asn, 0);
890 : :
891 : 4 : content = egg_asn1x_get_value_raw (egg_asn1x_node (asn, "modulus", NULL));
892 [ - + ]: 4 : if (!content)
893 : 0 : g_return_val_if_reached (0);
894 : :
895 : 4 : egg_asn1x_destroy (asn);
896 : :
897 : : /* Removes the complement */
898 : 4 : key_size = (g_bytes_get_size (content) / 2) * 2 * 8;
899 : :
900 : 4 : g_bytes_unref (content);
901 : 4 : return key_size;
902 : : }
903 : :
904 : : static guint
905 : 0 : attributes_rsa_key_size (GckAttributes *attrs)
906 : : {
907 : : const GckAttribute *attr;
908 : : gulong bits;
909 : :
910 : 0 : attr = gck_attributes_find (attrs, CKA_MODULUS);
911 : :
912 : : /* Calculate the bit length, and remove the complement */
913 [ # # ]: 0 : if (attr != NULL)
914 : 0 : return (attr->length / 2) * 2 * 8;
915 : :
916 [ # # ]: 0 : if (gck_attributes_find_ulong (attrs, CKA_MODULUS_BITS, &bits))
917 : 0 : return (gint)bits;
918 : :
919 : 0 : return 0;
920 : : }
921 : :
922 : : static guint
923 : 5 : calculate_dsa_params_size (GNode *params)
924 : : {
925 : : GNode *asn;
926 : : GBytes *content;
927 : : guint key_size;
928 : :
929 : 5 : asn = egg_asn1x_get_any_as (params, pk_asn1_tab, "DSAParameters");
930 [ - + ]: 5 : g_return_val_if_fail (asn, 0);
931 : :
932 : 5 : content = egg_asn1x_get_value_raw (egg_asn1x_node (asn, "p", NULL));
933 [ - + ]: 5 : if (!content)
934 : 0 : g_return_val_if_reached (0);
935 : :
936 : 5 : egg_asn1x_destroy (asn);
937 : :
938 : : /* Removes the complement */
939 : 5 : key_size = (g_bytes_get_size (content) / 2) * 2 * 8;
940 : :
941 : 5 : g_bytes_unref (content);
942 : 5 : return key_size;
943 : : }
944 : :
945 : : static guint
946 : 0 : attributes_dsa_key_size (GckAttributes *attrs)
947 : : {
948 : : const GckAttribute *attr;
949 : : gulong bits;
950 : :
951 : 0 : attr = gck_attributes_find (attrs, CKA_PRIME);
952 : :
953 : : /* Calculate the bit length, and remove the complement */
954 [ # # ]: 0 : if (attr != NULL)
955 : 0 : return (attr->length / 2) * 2 * 8;
956 : :
957 [ # # ]: 0 : if (gck_attributes_find_ulong (attrs, CKA_PRIME_BITS, &bits))
958 : 0 : return (gint)bits;
959 : :
960 : 0 : return 0;
961 : : }
962 : :
963 : : static guint
964 : 3 : named_curve_size (GNode *params)
965 : : {
966 : : GQuark oid;
967 : : guint size;
968 : :
969 : 3 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (params, "namedCurve", NULL));
970 [ - + ]: 3 : if (oid == GCR_OID_EC_SECP192R1)
971 : 0 : size = 192;
972 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT163K1)
973 : 0 : size = 163;
974 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT163R2)
975 : 0 : size = 163;
976 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECP224R1)
977 : 0 : size = 224;
978 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT233K1)
979 : 0 : size = 233;
980 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT233R1)
981 : 0 : size = 233;
982 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECP256R1)
983 : 0 : size = 256;
984 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT283K1)
985 : 0 : size = 283;
986 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT283R1)
987 : 0 : size = 283;
988 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECP384R1)
989 : 0 : size = 384;
990 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT409K1)
991 : 0 : size = 409;
992 [ - + ]: 3 : else if (oid == GCR_OID_EC_SECT409R1)
993 : 0 : size = 409;
994 [ + - ]: 3 : else if (oid == GCR_OID_EC_SECP521R1)
995 : 3 : size = 521;
996 [ # # ]: 0 : else if (oid == GCR_OID_EC_SECP571K1)
997 : 0 : size = 571;
998 [ # # ]: 0 : else if (oid == GCR_OID_EC_SECT571R1)
999 : 0 : size = 571;
1000 : : else
1001 : 0 : size = 0;
1002 : 3 : return size;
1003 : :
1004 : : }
1005 : :
1006 : : static guint
1007 : 3 : calculate_ec_params_size (GNode *params)
1008 : : {
1009 : : GNode *asn;
1010 : : guint size;
1011 : :
1012 : 3 : asn = egg_asn1x_get_any_as (params, pk_asn1_tab, "ECParameters");
1013 [ - + ]: 3 : g_return_val_if_fail (asn, 0);
1014 : :
1015 : 3 : size = named_curve_size (asn);
1016 : 3 : egg_asn1x_destroy (asn);
1017 : :
1018 : 3 : return size;
1019 : : }
1020 : :
1021 : : static guint
1022 : 0 : gost_curve_size (GNode *params)
1023 : : {
1024 : : GQuark oid;
1025 : : guint size;
1026 : :
1027 : 0 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (params, "publicKeyParamSet", NULL));
1028 [ # # ]: 0 : if (oid == GCR_OID_GOSTR3410_TEST ||
1029 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_CRYPTOPRO_A ||
1030 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_CRYPTOPRO_B ||
1031 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_CRYPTOPRO_C ||
1032 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_CRYPTOPRO_XCHA ||
1033 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_CRYPTOPRO_XCHB ||
1034 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC256A ||
1035 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC256B ||
1036 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC256C ||
1037 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC256D)
1038 : 0 : size = 256;
1039 [ # # ]: 0 : else if (oid == GCR_OID_GOSTR3410_512_TEST ||
1040 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC512A ||
1041 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC512B ||
1042 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_GC512C)
1043 : 0 : size = 512;
1044 : : else {
1045 : 0 : g_message ("unsupported curve: %s", g_quark_to_string (oid));
1046 : 0 : size = 0;
1047 : : }
1048 : 0 : return size;
1049 : :
1050 : : }
1051 : :
1052 : : static guint
1053 : 0 : calculate_gost_params_size (GNode *params, gboolean gost2012)
1054 : : {
1055 : : GNode *asn;
1056 : : guint size;
1057 : :
1058 [ # # ]: 0 : asn = egg_asn1x_get_any_as (params, pk_asn1_tab,
1059 : : gost2012 ?
1060 : : "GostR3410-2012-PublicKeyParameters" :
1061 : : "GostR3410-2001-PublicKeyParameters");
1062 [ # # ]: 0 : g_return_val_if_fail (asn, 0);
1063 : :
1064 : 0 : size = gost_curve_size (asn);
1065 : 0 : egg_asn1x_destroy (asn);
1066 : :
1067 : 0 : return size;
1068 : : }
1069 : :
1070 : : static guint
1071 : 0 : attributes_ec_params_size (GckAttributes *attrs)
1072 : : {
1073 : : GNode *asn;
1074 : : const GckAttribute *attr;
1075 : : GBytes *bytes;
1076 : 0 : guint size = 0;
1077 : :
1078 : 0 : attr = gck_attributes_find (attrs, CKA_EC_PARAMS);
1079 : :
1080 : : /* Calculate the bit length, and remove the complement */
1081 [ # # # # ]: 0 : if (attr && !gck_attribute_is_invalid (attr)) {
1082 : 0 : bytes = g_bytes_new_with_free_func (attr->value, attr->length,
1083 : : gck_attributes_unref,
1084 : 0 : gck_attributes_ref (attrs));
1085 : 0 : asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECParameters", bytes);
1086 : 0 : g_bytes_unref (bytes);
1087 : :
1088 [ # # ]: 0 : if (asn)
1089 : 0 : size = named_curve_size (asn);
1090 : 0 : egg_asn1x_destroy (asn);
1091 : : }
1092 : :
1093 : 0 : return size;
1094 : : }
1095 : :
1096 : : guint
1097 : 12 : _gcr_subject_public_key_calculate_size (GNode *subject_public_key)
1098 : : {
1099 : : GBytes *key;
1100 : : GNode *params;
1101 : 12 : guint key_size = 0;
1102 : : guint n_bits;
1103 : : GQuark oid;
1104 : :
1105 : : /* Figure out the algorithm */
1106 : 12 : oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (subject_public_key,
1107 : : "algorithm", "algorithm", NULL));
1108 [ - + ]: 12 : g_return_val_if_fail (oid != 0, 0);
1109 : :
1110 : : /* RSA keys are stored in the main subjectPublicKey field */
1111 [ + + ]: 12 : if (oid == GCR_OID_PKIX1_RSA) {
1112 : 4 : key = egg_asn1x_get_bits_as_raw (egg_asn1x_node (subject_public_key, "subjectPublicKey", NULL), &n_bits);
1113 [ - + ]: 4 : g_return_val_if_fail (key != NULL, 0);
1114 : 4 : key_size = calculate_rsa_key_size (key);
1115 : 4 : g_bytes_unref (key);
1116 : :
1117 : : /* The DSA key size is discovered by the prime in params */
1118 [ + + ]: 8 : } else if (oid == GCR_OID_PKIX1_DSA) {
1119 : 5 : params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
1120 : 5 : key_size = calculate_dsa_params_size (params);
1121 : :
1122 [ + - ]: 3 : } else if (oid == GCR_OID_PKIX1_EC) {
1123 : 3 : params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
1124 : 3 : key_size = calculate_ec_params_size (params);
1125 : :
1126 [ # # ]: 0 : } else if (oid == GCR_OID_GOSTR3410_2001) {
1127 : 0 : params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
1128 : 0 : key_size = calculate_gost_params_size (params, FALSE);
1129 : :
1130 [ # # ]: 0 : } else if (oid == GCR_OID_GOSTR3410_2012_256 ||
1131 [ # # ]: 0 : oid == GCR_OID_GOSTR3410_2012_512) {
1132 : 0 : params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
1133 : 0 : key_size = calculate_gost_params_size (params, TRUE);
1134 : :
1135 : : } else {
1136 : 0 : g_message ("unsupported key algorithm: %s", g_quark_to_string (oid));
1137 : : }
1138 : :
1139 : 12 : return key_size;
1140 : : }
1141 : :
1142 : : guint
1143 : 0 : _gcr_subject_public_key_attributes_size (GckAttributes *attrs)
1144 : : {
1145 : : gulong key_type;
1146 : :
1147 [ # # ]: 0 : if (!gck_attributes_find_ulong (attrs, CKA_KEY_TYPE, &key_type))
1148 : 0 : return 0;
1149 : :
1150 [ # # # # ]: 0 : switch (key_type) {
1151 : 0 : case CKK_RSA:
1152 : 0 : return attributes_rsa_key_size (attrs);
1153 : 0 : case CKK_DSA:
1154 : 0 : return attributes_dsa_key_size (attrs);
1155 : 0 : case CKK_EC:
1156 : 0 : return attributes_ec_params_size (attrs);
1157 : 0 : default:
1158 : 0 : g_message ("unsupported key algorithm: %lu", key_type);
1159 : 0 : return 0;
1160 : : }
1161 : : }
|