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-data-der.h"
25 : #include "gkm-util.h"
26 :
27 : #include "egg/egg-timegm.h"
28 :
29 : #include <stdarg.h>
30 : #include <stdio.h>
31 : #include <stdlib.h>
32 : #include <string.h>
33 :
34 :
35 : CK_RV
36 27 : gkm_attribute_get_bool (CK_ATTRIBUTE_PTR attr, gboolean *value)
37 : {
38 : CK_BBOOL* bool;
39 :
40 27 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
41 27 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
42 :
43 27 : if (attr->ulValueLen != sizeof (CK_BBOOL) || attr->pValue == NULL)
44 2 : return CKR_ATTRIBUTE_VALUE_INVALID;
45 :
46 25 : bool = attr->pValue;
47 25 : *value = *bool ? TRUE : FALSE;
48 25 : return CKR_OK;
49 : }
50 :
51 : CK_RV
52 0 : gkm_attribute_get_ulong (CK_ATTRIBUTE_PTR attr, CK_ULONG *value)
53 : {
54 : CK_ULONG* ulong;
55 :
56 0 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
57 0 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
58 :
59 0 : if (attr->ulValueLen != sizeof (CK_ULONG) || attr->pValue == NULL)
60 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
61 :
62 0 : ulong = attr->pValue;
63 0 : *value = *ulong;
64 0 : return CKR_OK;
65 : }
66 :
67 : CK_RV
68 4 : gkm_attribute_get_time (CK_ATTRIBUTE_PTR attr, glong *when)
69 : {
70 : struct tm tm;
71 : gchar buf[15];
72 : time_t time;
73 :
74 4 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
75 4 : g_return_val_if_fail (when, CKR_GENERAL_ERROR);
76 :
77 4 : if (attr->ulValueLen == 0) {
78 1 : *when = (glong)-1;
79 1 : return CKR_OK;
80 : }
81 :
82 3 : if (!attr->pValue || attr->ulValueLen != 16)
83 1 : return CKR_ATTRIBUTE_VALUE_INVALID;
84 :
85 2 : memset (&tm, 0, sizeof (tm));
86 2 : memcpy (buf, attr->pValue, 14);
87 2 : buf[14] = 0;
88 :
89 2 : if (!strptime(buf, "%Y%m%d%H%M%S", &tm))
90 1 : return CKR_ATTRIBUTE_VALUE_INVALID;
91 :
92 : /* Convert to seconds since epoch */
93 1 : time = timegm (&tm);
94 1 : if (time < 0)
95 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
96 :
97 1 : *when = time;
98 1 : return CKR_OK;
99 : }
100 :
101 : CK_RV
102 83 : gkm_attribute_get_string (CK_ATTRIBUTE_PTR attr, gchar **value)
103 : {
104 83 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
105 83 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
106 :
107 83 : if (attr->ulValueLen == 0) {
108 1 : *value = NULL;
109 1 : return CKR_OK;
110 : }
111 :
112 82 : if (!attr->pValue)
113 1 : return CKR_ATTRIBUTE_VALUE_INVALID;
114 :
115 81 : if (!g_utf8_validate (attr->pValue, attr->ulValueLen, NULL))
116 1 : return CKR_ATTRIBUTE_VALUE_INVALID;
117 :
118 80 : *value = g_strndup (attr->pValue, attr->ulValueLen);
119 80 : return CKR_OK;
120 : }
121 :
122 : CK_RV
123 1 : gkm_attribute_get_bytes (CK_ATTRIBUTE_PTR attr, GBytes **value)
124 : {
125 1 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
126 1 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
127 :
128 1 : if (attr->ulValueLen == 0) {
129 0 : *value = NULL;
130 0 : return CKR_OK;
131 : }
132 :
133 1 : if (!attr->pValue)
134 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
135 :
136 1 : *value = g_bytes_new (attr->pValue, attr->ulValueLen);
137 1 : return CKR_OK;
138 : }
139 :
140 : CK_RV
141 16 : gkm_attribute_get_mpi (CK_ATTRIBUTE_PTR attr, gcry_mpi_t *value)
142 : {
143 : gcry_error_t gcry;
144 :
145 16 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
146 16 : g_return_val_if_fail (value, CKR_GENERAL_ERROR);
147 :
148 16 : gcry = gcry_mpi_scan (value, GCRYMPI_FMT_USG, attr->pValue, attr->ulValueLen, NULL);
149 16 : if (gcry != 0)
150 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
151 :
152 16 : return CKR_OK;
153 : }
154 :
155 : CK_RV
156 6 : gkm_attribute_get_template (CK_ATTRIBUTE_PTR attr, GArray **template)
157 : {
158 : CK_ULONG n_attrs;
159 :
160 6 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
161 6 : g_return_val_if_fail (attr, CKR_GENERAL_ERROR);
162 :
163 : /* Validate everything first */
164 6 : if (attr->ulValueLen % sizeof (CK_ATTRIBUTE) != 0)
165 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
166 :
167 6 : n_attrs = attr->ulValueLen / sizeof (CK_ATTRIBUTE);
168 6 : if (n_attrs != 0 && !attr->pValue)
169 0 : return CKR_ATTRIBUTE_VALUE_INVALID;
170 :
171 6 : *template = gkm_template_new (attr->pValue, n_attrs);
172 6 : return CKR_OK;
173 : }
174 :
175 : CK_RV
176 3 : gkm_attribute_set_empty (CK_ATTRIBUTE_PTR attr)
177 : {
178 3 : return gkm_attribute_set_data (attr, "", 0);
179 : }
180 :
181 : CK_RV
182 248 : gkm_attribute_set_bool (CK_ATTRIBUTE_PTR attr, CK_BBOOL value)
183 : {
184 248 : return gkm_attribute_set_data (attr, &value, sizeof (CK_BBOOL));
185 : }
186 :
187 : CK_RV
188 5907 : gkm_attribute_set_ulong (CK_ATTRIBUTE_PTR attr, CK_ULONG value)
189 : {
190 5907 : return gkm_attribute_set_data (attr, &value, sizeof (CK_ULONG));
191 : }
192 :
193 : CK_RV
194 5158 : gkm_attribute_set_string (CK_ATTRIBUTE_PTR attr, const gchar* string)
195 : {
196 10313 : return gkm_attribute_set_data (attr, (CK_VOID_PTR)string,
197 5155 : string ? strlen (string) : 0);
198 : }
199 :
200 : CK_RV
201 4 : gkm_attribute_set_date (CK_ATTRIBUTE_PTR attr, time_t time)
202 : {
203 : CK_DATE date;
204 : struct tm tm;
205 : gchar buf[16];
206 :
207 : /* 'Empty' date as defined in PKCS#11 */
208 4 : if (time == (time_t)-1)
209 1 : return gkm_attribute_set_data (attr, NULL, 0);
210 :
211 3 : if (!attr->pValue) {
212 1 : attr->ulValueLen = sizeof (CK_DATE);
213 1 : return CKR_OK;
214 : }
215 :
216 2 : if (!gmtime_r (&time, &tm))
217 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
218 :
219 : g_assert (sizeof (date.year) == 4);
220 2 : if (G_UNLIKELY (snprintf ((char*)buf, 5, "%04d", 1900 + tm.tm_year) < 0))
221 0 : abort ();
222 2 : memcpy (date.year, buf, 4);
223 :
224 : g_assert (sizeof (date.month) == 2);
225 2 : if (G_UNLIKELY (snprintf ((char*)buf, 3, "%02d", tm.tm_mon + 1) < 0))
226 0 : abort ();
227 2 : memcpy (date.month, buf, 2);
228 :
229 : g_assert (sizeof (date.day) == 2);
230 2 : if (G_UNLIKELY (snprintf ((char*)buf, 3, "%02d", tm.tm_mday) < 0))
231 0 : abort ();
232 2 : memcpy (date.day, buf, 2);
233 :
234 2 : return gkm_attribute_set_data (attr, &date, sizeof (date));
235 : }
236 :
237 : CK_RV
238 9 : gkm_attribute_set_time (CK_ATTRIBUTE_PTR attr, glong when)
239 : {
240 : struct tm tm;
241 : gchar buf[20];
242 :
243 : /* 'Empty' time as defined in PKCS#11 */
244 9 : if (when == (glong)-1)
245 1 : return gkm_attribute_set_data (attr, NULL, 0);
246 :
247 8 : if (!attr->pValue) {
248 3 : attr->ulValueLen = 16;
249 3 : return CKR_OK;
250 : }
251 :
252 5 : time_t time = when;
253 5 : if (!gmtime_r (&time, &tm))
254 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
255 :
256 5 : if (!strftime(buf, sizeof (buf), "%Y%m%d%H%M%S00", &tm))
257 0 : g_return_val_if_reached (CKR_GENERAL_ERROR);
258 :
259 5 : return gkm_attribute_set_data (attr, buf, 16);
260 : }
261 :
262 : CK_RV
263 11572 : gkm_attribute_set_data (CK_ATTRIBUTE_PTR attr, gconstpointer value, gsize n_value)
264 : {
265 11572 : CK_RV rv = gkm_util_return_data (attr->pValue, &(attr->ulValueLen), value, n_value);
266 11572 : if (rv == CKR_BUFFER_TOO_SMALL)
267 6 : attr->ulValueLen = (CK_ULONG)-1;
268 11572 : return rv;
269 : }
270 :
271 : CK_RV
272 66 : gkm_attribute_set_bytes (CK_ATTRIBUTE_PTR attr,
273 : GBytes *value)
274 : {
275 66 : return gkm_attribute_set_data (attr, g_bytes_get_data (value, NULL),
276 : g_bytes_get_size (value));
277 : }
278 :
279 : CK_RV
280 10 : gkm_attribute_set_mpi (CK_ATTRIBUTE_PTR attr, gcry_mpi_t mpi)
281 : {
282 : gsize len;
283 : gcry_error_t gcry;
284 :
285 10 : g_assert (attr);
286 10 : g_assert (mpi);
287 :
288 : /* Get the size */
289 10 : gcry = gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &len, mpi);
290 10 : g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
291 :
292 10 : if (!attr->pValue) {
293 2 : attr->ulValueLen = len;
294 2 : return CKR_OK;
295 : }
296 :
297 8 : if (len > attr->ulValueLen) {
298 1 : attr->ulValueLen = (CK_ULONG)-1;
299 1 : return CKR_BUFFER_TOO_SMALL;
300 : }
301 :
302 : /* Write in directly to attribute */
303 7 : gcry = gcry_mpi_print (GCRYMPI_FMT_USG, attr->pValue, len, &len, mpi);
304 7 : g_return_val_if_fail (gcry == 0, CKR_GENERAL_ERROR);
305 :
306 7 : attr->ulValueLen = len;
307 7 : return CKR_OK;
308 : }
309 :
310 : CK_RV
311 2 : gkm_attribute_set_template (CK_ATTRIBUTE_PTR attr, GArray *template)
312 : {
313 : CK_ATTRIBUTE_PTR array;
314 : CK_ATTRIBUTE_PTR at;
315 : CK_RV rv;
316 : gulong len;
317 : gulong i;
318 :
319 2 : g_assert (attr);
320 2 : g_warn_if_fail ((attr->type & CKF_ARRAY_ATTRIBUTE) != 0);
321 :
322 2 : len = sizeof (CK_ATTRIBUTE) * template->len;
323 2 : if (!attr->pValue) {
324 0 : attr->ulValueLen = len;
325 0 : return CKR_OK;
326 2 : } else if (len > attr->ulValueLen) {
327 2 : attr->ulValueLen = (CK_ULONG)-1;
328 2 : return CKR_BUFFER_TOO_SMALL;
329 : }
330 :
331 0 : attr->ulValueLen = len;
332 0 : array = attr->pValue;
333 0 : rv = CKR_OK;
334 :
335 : /* Start working with individual elements */
336 0 : for (i = 0; i < template->len; ++i) {
337 0 : at = &g_array_index (template, CK_ATTRIBUTE, i);
338 0 : array[i].type = at->type;
339 0 : if (!array[i].pValue) {
340 0 : array[i].ulValueLen = at->ulValueLen;
341 0 : } else if (array[i].ulValueLen < at->ulValueLen) {
342 0 : array[i].ulValueLen = (CK_ULONG)-1;
343 0 : rv = CKR_BUFFER_TOO_SMALL;
344 : } else {
345 0 : memcpy(array[i].pValue, at->pValue, at->ulValueLen);
346 0 : array[i].ulValueLen = at->ulValueLen;
347 : }
348 : }
349 :
350 0 : return rv;
351 : }
352 :
353 : CK_RV
354 18 : gkm_attribute_set_checksum (CK_ATTRIBUTE_PTR attr, GChecksumType ctype,
355 : gconstpointer data, gsize n_data)
356 : {
357 : GChecksum *checksum;
358 : gssize length;
359 : gsize result;
360 :
361 18 : g_assert (attr);
362 :
363 18 : g_return_val_if_fail (data, CKR_GENERAL_ERROR);
364 18 : g_return_val_if_fail (n_data, CKR_GENERAL_ERROR);
365 :
366 18 : length = g_checksum_type_get_length (ctype);
367 18 : g_return_val_if_fail (length > 0, CKR_GENERAL_ERROR);
368 :
369 : /* Just asking for the length */
370 18 : if (!attr->pValue) {
371 0 : attr->ulValueLen = length;
372 0 : return CKR_OK;
373 : }
374 :
375 : /* Buffer is too short */
376 18 : if (length > attr->ulValueLen) {
377 0 : attr->ulValueLen = length;
378 0 : return CKR_BUFFER_TOO_SMALL;
379 : }
380 :
381 18 : checksum = g_checksum_new (ctype);
382 18 : g_checksum_update (checksum, data, n_data);
383 18 : result = attr->ulValueLen;
384 18 : g_checksum_get_digest (checksum, attr->pValue, &result);
385 18 : g_checksum_free (checksum);
386 18 : attr->ulValueLen = result;
387 18 : return CKR_OK;
388 : }
389 :
390 : gboolean
391 20185 : gkm_attribute_equal (gconstpointer v1, gconstpointer v2)
392 : {
393 20185 : const CK_ATTRIBUTE *a1 = v1;
394 20185 : const CK_ATTRIBUTE *a2 = v2;
395 :
396 20185 : g_assert (a1);
397 20185 : g_assert (a2);
398 :
399 20185 : if (a1 == a2)
400 10498 : return TRUE;
401 9687 : if (a1->type != a2->type)
402 3207 : return FALSE;
403 6480 : if (a1->ulValueLen != a2->ulValueLen)
404 7 : return FALSE;
405 6473 : if (a1->pValue == a2->pValue)
406 4 : return TRUE;
407 6469 : if (a1->ulValueLen == 0)
408 1 : return TRUE;
409 :
410 6468 : g_assert (a1->pValue);
411 6468 : g_assert (a2->pValue);
412 :
413 6468 : return memcmp (a1->pValue, a2->pValue, a1->ulValueLen) == 0;
414 : }
415 :
416 : guint
417 29314 : gkm_attribute_hash (gconstpointer v)
418 : {
419 29314 : const CK_ATTRIBUTE *a = v;
420 : const signed char *p;
421 : guint i, h;
422 :
423 29314 : g_assert (a);
424 :
425 29314 : p = (const signed char*)&(a->type);
426 29314 : h = *p;
427 263826 : for(i = 0; i < sizeof (CK_ATTRIBUTE_PTR); ++i)
428 234512 : h = (h << 5) - h + *(p++);
429 :
430 29314 : p = a->pValue;
431 264601 : for(i = 0; i < a->ulValueLen; ++i)
432 235287 : h = (h << 5) - h + *(p++);
433 :
434 29314 : return h;
435 : }
436 :
437 : gboolean
438 2812 : gkm_attribute_consumed (CK_ATTRIBUTE_PTR attr)
439 : {
440 2812 : g_return_val_if_fail (attr, FALSE);
441 2812 : return attr->type == (CK_ULONG)-1;
442 : }
443 :
444 : void
445 46 : gkm_attribute_consume (CK_ATTRIBUTE_PTR attr)
446 : {
447 46 : attr->type = (CK_ULONG)-1;
448 46 : }
449 :
450 : void
451 577 : gkm_attributes_consume (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, ...)
452 : {
453 : CK_ATTRIBUTE_TYPE type;
454 : GArray *types;
455 : guint i, j;
456 : va_list va;
457 :
458 : /* Convert the var args into an array */
459 577 : types = g_array_new (FALSE, TRUE, sizeof (CK_ATTRIBUTE_TYPE));
460 577 : va_start (va, n_attrs);
461 1807 : while ((type = va_arg (va, CK_ATTRIBUTE_TYPE)) != G_MAXULONG)
462 1230 : g_array_append_val (types, type);
463 577 : va_end (va);
464 :
465 : /* Consume each attribute whose type was in the var args */
466 2719 : for (i = 0; i < n_attrs; ++i) {
467 2142 : if (gkm_attribute_consumed (&attrs[i]))
468 742 : continue;
469 3946 : for (j = 0; j < types->len; ++j) {
470 2941 : if (attrs[i].type == g_array_index (types, CK_ATTRIBUTE_TYPE, j)) {
471 395 : attrs[i].type = (CK_ULONG)-1;
472 395 : break;
473 : }
474 : }
475 : }
476 :
477 577 : g_array_free (types, TRUE);
478 577 : }
479 :
480 : gboolean
481 1026 : gkm_attributes_contains (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, CK_ATTRIBUTE_PTR attr)
482 : {
483 : CK_ULONG i;
484 :
485 1026 : g_assert (attrs || !n_attrs);
486 1026 : g_assert (attr);
487 :
488 5037 : for (i = 0; i < n_attrs; ++i) {
489 4214 : if (gkm_attribute_equal (attr, &attrs[i]))
490 203 : return TRUE;
491 : }
492 :
493 823 : return FALSE;
494 : }
495 :
496 : CK_ATTRIBUTE_PTR
497 3549 : gkm_attributes_find (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, CK_ATTRIBUTE_TYPE type)
498 : {
499 : CK_ULONG i;
500 :
501 3549 : g_assert (attrs || !n_attrs);
502 :
503 15902 : for (i = 0; i < n_attrs; ++i) {
504 14081 : if(attrs[i].type == type && attrs[i].ulValueLen != (CK_ULONG)-1)
505 1728 : return &attrs[i];
506 : }
507 :
508 1821 : return NULL;
509 : }
510 :
511 : gboolean
512 715 : gkm_attributes_find_boolean (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, CK_ATTRIBUTE_TYPE type, gboolean *value)
513 : {
514 : CK_ATTRIBUTE_PTR attr;
515 :
516 715 : g_assert (attrs || !n_attrs);
517 :
518 715 : attr = gkm_attributes_find (attrs, n_attrs, type);
519 715 : if (attr == NULL)
520 424 : return FALSE;
521 :
522 291 : if (attr->ulValueLen != sizeof (CK_BBOOL))
523 1 : return FALSE;
524 :
525 290 : if (value != NULL) {
526 : CK_BBOOL bbool;
527 290 : memcpy (&bbool, attr->pValue, sizeof (CK_BBOOL));
528 290 : *value = bbool == CK_TRUE ? TRUE : FALSE;
529 : }
530 :
531 290 : return TRUE;
532 : }
533 :
534 : gboolean
535 670 : gkm_attributes_find_ulong (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs, CK_ATTRIBUTE_TYPE type, gulong *value)
536 : {
537 : CK_ATTRIBUTE_PTR attr;
538 :
539 670 : g_assert (attrs || !n_attrs);
540 :
541 670 : attr = gkm_attributes_find (attrs, n_attrs, type);
542 670 : if (attr == NULL)
543 401 : return FALSE;
544 :
545 269 : if (attr->ulValueLen != sizeof (CK_ULONG))
546 1 : return FALSE;
547 :
548 268 : if (value != NULL) {
549 : CK_ULONG ulong;
550 268 : memcpy (&ulong, attr->pValue, sizeof (CK_ULONG));
551 268 : *value = ulong;
552 : }
553 :
554 268 : return TRUE;
555 : }
556 :
557 : gboolean
558 15 : gkm_attributes_find_mpi (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
559 : CK_ATTRIBUTE_TYPE type, gcry_mpi_t *value)
560 : {
561 : CK_ATTRIBUTE_PTR attr;
562 :
563 15 : g_assert (attrs || !n_attrs);
564 :
565 15 : attr = gkm_attributes_find (attrs, n_attrs, type);
566 15 : if (attr == NULL)
567 1 : return FALSE;
568 :
569 14 : return gkm_attribute_get_mpi (attr, value) == CKR_OK;
570 : }
571 :
572 : gboolean
573 89 : gkm_attributes_find_string (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
574 : CK_ATTRIBUTE_TYPE type, gchar **value)
575 : {
576 : CK_ATTRIBUTE_PTR attr;
577 :
578 89 : g_return_val_if_fail (attrs || !n_attrs, FALSE);
579 :
580 89 : attr = gkm_attributes_find (attrs, n_attrs, type);
581 89 : if (attr == NULL)
582 46 : return FALSE;
583 :
584 43 : return gkm_attribute_get_string (attr, value) == CKR_OK;
585 : }
586 :
587 : /* Need to get DER encoded EC parameters and point */
588 : gboolean
589 1 : gkm_attributes_find_bytes (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs,
590 : CK_ATTRIBUTE_TYPE type, GBytes **value)
591 : {
592 : CK_ATTRIBUTE_PTR attr;
593 :
594 1 : g_return_val_if_fail (attrs || !n_attrs, FALSE);
595 :
596 1 : attr = gkm_attributes_find (attrs, n_attrs, type);
597 1 : if (attr == NULL)
598 0 : return FALSE;
599 :
600 1 : return gkm_attribute_get_bytes (attr, value) == CKR_OK;
601 : }
602 :
603 : GArray*
604 598 : gkm_template_new (CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs)
605 : {
606 598 : GArray *template = g_array_new (FALSE, FALSE, sizeof (CK_ATTRIBUTE));
607 : CK_ATTRIBUTE_PTR pat;
608 : gulong i;
609 :
610 598 : g_return_val_if_fail (attrs || !n_attrs, NULL);
611 :
612 598 : g_array_append_vals (template, attrs, n_attrs);
613 1935 : for (i = 0; i < n_attrs; ++i) {
614 1337 : pat = &g_array_index (template, CK_ATTRIBUTE, i);
615 1337 : if (pat->pValue) {
616 1321 : g_return_val_if_fail (pat->ulValueLen != (CK_ULONG)-1, NULL);
617 1321 : pat->pValue = g_memdup (pat->pValue, pat->ulValueLen ? pat->ulValueLen : 1);
618 : }
619 : }
620 :
621 598 : return template;
622 : }
623 :
624 : void
625 1550 : gkm_template_set (GArray *template, CK_ATTRIBUTE_PTR attr)
626 : {
627 : CK_ATTRIBUTE at;
628 : guint i;
629 :
630 1550 : g_return_if_fail (template);
631 1550 : g_return_if_fail (attr);
632 1550 : g_return_if_fail (attr->ulValueLen != (CK_ULONG)-1);
633 :
634 : /* Remove any previous value */
635 6449 : for (i = 0; i < template->len; ++i) {
636 4909 : if (g_array_index (template, CK_ATTRIBUTE, i).type == attr->type) {
637 10 : g_free (g_array_index (template, CK_ATTRIBUTE, i).pValue);
638 10 : g_array_remove_index_fast (template, i);
639 10 : break;
640 : }
641 : }
642 :
643 : /* Add a new attribute */
644 1550 : memcpy (&at, attr, sizeof (at));
645 1550 : if (at.pValue)
646 1540 : at.pValue = g_memdup (at.pValue, at.ulValueLen ? at.ulValueLen : 1);
647 1550 : g_array_append_vals (template, &at, 1);
648 : }
649 :
650 : void
651 179 : gkm_template_set_value (GArray *template, CK_ATTRIBUTE_TYPE type,
652 : CK_VOID_PTR value, CK_ULONG length)
653 : {
654 : CK_ATTRIBUTE attr;
655 179 : g_return_if_fail (template);
656 :
657 179 : attr.type = type;
658 179 : attr.pValue = value;
659 179 : attr.ulValueLen = length;
660 179 : gkm_template_set (template, &attr);
661 : }
662 :
663 : void
664 523 : gkm_template_set_string (GArray *template, CK_ATTRIBUTE_TYPE type, const gchar *value)
665 : {
666 : CK_ATTRIBUTE attr;
667 523 : g_return_if_fail (template);
668 523 : g_return_if_fail (value);
669 :
670 523 : attr.type = type;
671 523 : attr.pValue = (CK_VOID_PTR)value;
672 523 : attr.ulValueLen = strlen (value);
673 523 : gkm_template_set (template, &attr);
674 :
675 : }
676 : void
677 239 : gkm_template_set_ulong (GArray *template, CK_ATTRIBUTE_TYPE type, CK_ULONG value)
678 : {
679 : CK_ATTRIBUTE attr;
680 239 : g_return_if_fail (template);
681 :
682 239 : attr.type = type;
683 239 : attr.pValue = &value;
684 239 : attr.ulValueLen = sizeof (value);
685 239 : gkm_template_set (template, &attr);
686 :
687 : }
688 :
689 : void
690 554 : gkm_template_set_boolean (GArray *template, CK_ATTRIBUTE_TYPE type, CK_BBOOL value)
691 : {
692 : CK_ATTRIBUTE attr;
693 554 : g_return_if_fail (template);
694 :
695 554 : attr.type = type;
696 554 : attr.pValue = &value;
697 554 : attr.ulValueLen = sizeof (value);
698 554 : gkm_template_set (template, &attr);
699 : }
700 :
701 : void
702 598 : gkm_template_free (GArray *template)
703 : {
704 : guint i;
705 :
706 598 : if (!template)
707 0 : return;
708 :
709 3475 : for (i = 0; i < template->len; ++i)
710 2877 : g_free (g_array_index (template, CK_ATTRIBUTE, i).pValue);
711 598 : g_array_free (template, TRUE);
712 : }
713 :
714 : CK_ATTRIBUTE_PTR
715 1497 : gkm_template_find (GArray *template, CK_ATTRIBUTE_TYPE type)
716 : {
717 1497 : g_return_val_if_fail (template, NULL);
718 1497 : return gkm_attributes_find ((CK_ATTRIBUTE_PTR)template->data, template->len, type);
719 : }
720 :
721 : gboolean
722 146 : gkm_template_find_boolean (GArray *template, CK_ATTRIBUTE_TYPE type, gboolean *value)
723 : {
724 146 : g_return_val_if_fail (template, FALSE);
725 146 : return gkm_attributes_find_boolean ((CK_ATTRIBUTE_PTR)template->data, template->len, type, value);
726 : }
727 :
728 : gboolean
729 103 : gkm_template_find_ulong (GArray *template, CK_ATTRIBUTE_TYPE type, gulong *value)
730 : {
731 103 : g_return_val_if_fail (template, FALSE);
732 103 : return gkm_attributes_find_ulong ((CK_ATTRIBUTE_PTR)template->data, template->len, type, value);
733 : }
|