1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <strings.h>
30 #include "metaGlobal.h"
31 #include "metaAttrMasters.h"
32
33 static void
34 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
35 size_t num_attributes, generic_attr_t **found_attribute);
36
37 /*
38 * get_master_attributes_by_object
39 *
40 * Returns an (statically allocated) set of object attributes, as determined by
41 * class and keytype of the supplied object. The attributes are only
42 * initialized to default values.
43 */
44 CK_RV
45 get_master_attributes_by_object(slot_session_t *session,
46 slot_object_t *slot_object, generic_attr_t **attributes,
47 size_t *num_attributes)
48 {
49 CK_RV rv;
50 CK_ATTRIBUTE attr;
51 CK_OBJECT_CLASS class;
52 CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
53
54 /* first get the class */
55 attr.type = CKA_CLASS;
56 attr.pValue = &class;
57 attr.ulValueLen = sizeof (class);
58 rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
59 session->hSession, slot_object->hObject, &attr, 1);
60 if (rv != CKR_OK) {
61 return (rv);
62 }
63
64 attr.pValue = &subtype;
65 attr.ulValueLen = sizeof (subtype);
66 switch (class) {
67 case CKO_CERTIFICATE:
68 attr.type = CKA_CERTIFICATE_TYPE;
69 break;
70 case CKO_HW_FEATURE:
71 attr.type = CKA_HW_FEATURE_TYPE;
72 break;
73 case CKO_PUBLIC_KEY:
74 case CKO_PRIVATE_KEY:
75 case CKO_SECRET_KEY:
76 case CKO_DOMAIN_PARAMETERS:
77 attr.type = CKA_KEY_TYPE;
78 break;
79 case CKO_DATA:
80 goto get_attr;
81 default:
82 /* should never be here */
83 return (CKR_ATTRIBUTE_VALUE_INVALID);
84 }
85 rv = FUNCLIST(session->fw_st_id)->C_GetAttributeValue(
86 session->hSession, slot_object->hObject, &attr, 1);
87 if (rv != CKR_OK) {
88 return (rv);
89 }
90
91 get_attr:
92 rv = get_master_attributes_by_type(class, subtype,
93 attributes, num_attributes);
94
95 return (rv);
96 }
97
98 /*
99 * get_master_attributes_by_template
100 *
101 * Returns an (statically allocated) set of object attributes, as determined by
102 * the supplied object template. The template is only used to determine the
103 * class/subclass of the object. The attributes are only initialized to
104 * default values.
105 */
106 CK_RV
107 get_master_attributes_by_template(
108 CK_ATTRIBUTE *template, CK_ULONG template_size,
109 generic_attr_t **attributes, size_t *num_attributes)
110 {
111 CK_OBJECT_CLASS class;
112 CK_ULONG subtype = CK_UNAVAILABLE_INFORMATION;
113 boolean_t found;
114
115 found = get_template_ulong(CKA_CLASS, template, template_size, &class);
116 if (!found) {
117 return (CKR_TEMPLATE_INCOMPLETE);
118 }
119
120 switch (class) {
121 case CKO_CERTIFICATE:
122 found = get_template_ulong(CKA_CERTIFICATE_TYPE,
123 template, template_size, &subtype);
124 break;
125 case CKO_HW_FEATURE:
126 found = get_template_ulong(CKA_HW_FEATURE_TYPE,
127 template, template_size, &subtype);
128 break;
129 case CKO_PUBLIC_KEY:
130 case CKO_PRIVATE_KEY:
131 case CKO_SECRET_KEY:
132 case CKO_DOMAIN_PARAMETERS:
133 found = get_template_ulong(CKA_KEY_TYPE,
134 template, template_size, &subtype);
135 break;
136 case CKO_DATA:
137 /* CKO_DATA has no subtype, just pretend it is found */
138 found = B_TRUE;
139 break;
140 default:
141 /* unknown object class */
142 return (CKR_ATTRIBUTE_VALUE_INVALID);
143 }
144
145 if (!found) {
146 return (CKR_TEMPLATE_INCOMPLETE);
147 }
148
149 return (get_master_attributes_by_type(class, subtype,
150 attributes, num_attributes));
151 }
152
153 /*
154 * get_master_template_by_type
155 *
156 * Returns an (statically allocated) set of object attributes, as determined
157 * by the specified class and subtype. The attributes are initialized to default
158 * values.
159 */
160 CK_RV
161 get_master_template_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
162 generic_attr_t **attributes, size_t *num_attributes)
163 {
164 generic_attr_t *master_template = NULL;
165 size_t master_template_size = 0;
166
167 switch (class) {
168 case CKO_HW_FEATURE:
169 switch (subtype) {
170 case CKO_HW_FEATURE:
171 master_template = (generic_attr_t *)OBJ_HW_CLOCK;
172 master_template_size = sizeof (OBJ_HW_CLOCK);
173 break;
174
175 case CKH_MONOTONIC_COUNTER:
176 master_template = (generic_attr_t *)OBJ_HW_MONOTONIC;
177 master_template_size = sizeof (OBJ_HW_MONOTONIC);
178 break;
179
180 default:
181 /* Unsupported. */
182 break;
183 }
184 break;
185
186 case CKO_DATA:
187 /* Objects of this class have no subtype. */
188 master_template = (generic_attr_t *)OBJ_DATA;
189 master_template_size = sizeof (OBJ_DATA);
190 break;
191
192 case CKO_CERTIFICATE:
193 switch (subtype) {
194 case CKC_X_509:
195 master_template = (generic_attr_t *)OBJ_CERT_X509;
196 master_template_size = sizeof (OBJ_CERT_X509);
197 break;
198
199 case CKC_X_509_ATTR_CERT:
200 master_template = (generic_attr_t *)OBJ_CERT_X509ATTR;
201 master_template_size = sizeof (OBJ_CERT_X509ATTR);
202 break;
203
204 default:
205 /* Unsupported. */
206 break;
207 }
208 break;
209
210 case CKO_PUBLIC_KEY:
211 switch (subtype) {
212 case CKK_RSA:
213 master_template = (generic_attr_t *)OBJ_PUBKEY_RSA;
214 master_template_size = sizeof (OBJ_PUBKEY_RSA);
215 break;
216
217 case CKK_DSA:
218 master_template = (generic_attr_t *)OBJ_PUBKEY_DSA;
219 master_template_size = sizeof (OBJ_PUBKEY_DSA);
220 break;
221
222 case CKK_EC:
223 master_template = (generic_attr_t *)OBJ_PUBKEY_EC;
224 master_template_size = sizeof (OBJ_PUBKEY_EC);
225 break;
226
227 case CKK_DH:
228 master_template = (generic_attr_t *)OBJ_PUBKEY_DH;
229 master_template_size = sizeof (OBJ_PUBKEY_DH);
230 break;
231
232 case CKK_X9_42_DH:
233 master_template = (generic_attr_t *)OBJ_PUBKEY_X942DH;
234 master_template_size = sizeof (OBJ_PUBKEY_X942DH);
235 break;
236
237 case CKK_KEA:
238 master_template = (generic_attr_t *)OBJ_PUBKEY_KEA;
239 master_template_size = sizeof (OBJ_PUBKEY_KEA);
240 break;
241
242 default:
243 /* Unsupported. */
244 break;
245 }
246 break;
247
248 case CKO_PRIVATE_KEY:
249 switch (subtype) {
250 case CKK_RSA:
251 master_template = (generic_attr_t *)OBJ_PRIVKEY_RSA;
252 master_template_size = sizeof (OBJ_PRIVKEY_RSA);
253 break;
254
255 case CKK_DSA:
256 master_template = (generic_attr_t *)OBJ_PRIVKEY_DSA;
257 master_template_size = sizeof (OBJ_PRIVKEY_DSA);
258 break;
259
260 case CKK_EC:
261 master_template = (generic_attr_t *)OBJ_PRIVKEY_EC;
262 master_template_size = sizeof (OBJ_PRIVKEY_EC);
263 break;
264
265 case CKK_DH:
266 master_template = (generic_attr_t *)OBJ_PRIVKEY_DH;
267 master_template_size = sizeof (OBJ_PRIVKEY_DH);
268 break;
269
270 case CKK_X9_42_DH:
271 master_template = (generic_attr_t *)OBJ_PRIVKEY_X942DH;
272 master_template_size = sizeof (OBJ_PRIVKEY_X942DH);
273 break;
274
275 case CKK_KEA:
276 master_template = (generic_attr_t *)OBJ_PRIVKEY_KEA;
277 master_template_size = sizeof (OBJ_PRIVKEY_KEA);
278 break;
279
280 default:
281 /* Unsupported. */
282 break;
283 }
284 break;
285
286 case CKO_SECRET_KEY:
287 /*
288 * The only difference between secret keys is that some
289 * are valiable length (eg CKK_AES), while others are not
290 * (eg CKK_DES) -- and do not have a CKA_VALUE_LEN attribute.
291 *
292 * FUTURE(?): Consider using obj_seckey_withlen for unknown
293 * keytypes. This is the most likely choice, as new algorithms
294 * seem to support variable length keys. That's not the default
295 * now, because if people have implemented new key types with
296 * different attribute sets (like the mess of public/private
297 * key types), then incorrect behaviour would result. It's
298 * easier to relax this restriction than to tighten it (which
299 * would introduce a regression to anyone relying on this
300 * working for unknown key types).
301 *
302 */
303 switch (subtype) {
304 case CKK_DES:
305 case CKK_DES2:
306 case CKK_DES3:
307 case CKK_IDEA:
308 case CKK_CDMF:
309 case CKK_SKIPJACK:
310 case CKK_BATON:
311 case CKK_JUNIPER:
312 master_template = (generic_attr_t *)OBJ_SECKEY;
313 master_template_size = sizeof (OBJ_SECKEY);
314 break;
315
316 case CKK_GENERIC_SECRET:
317 case CKK_RC2:
318 case CKK_RC4:
319 case CKK_RC5:
320 case CKK_AES:
321 case CKK_BLOWFISH:
322 case CKK_CAST:
323 case CKK_CAST3:
324 case CKK_CAST128:
325 master_template = (generic_attr_t *)OBJ_SECKEY_WITHLEN;
326 master_template_size = sizeof (OBJ_SECKEY_WITHLEN);
327 break;
328
329 default:
330 /* Unsupported. */
331 break;
332 }
333 break;
334
335 case CKO_DOMAIN_PARAMETERS:
336 switch (subtype) {
337 case CKK_DSA:
338 master_template = (generic_attr_t *)OBJ_DOM_DSA;
339 master_template_size = sizeof (OBJ_DOM_DSA);
340 break;
341
342 case CKK_DH:
343 master_template = (generic_attr_t *)OBJ_DOM_DH;
344 master_template_size = sizeof (OBJ_DOM_DH);
345 break;
346
347 case CKK_X9_42_DH:
348 master_template = (generic_attr_t *)OBJ_DOM_X942DH;
349 master_template_size = sizeof (OBJ_DOM_X942DH);
350 break;
351
352 default:
353 /* Unsupported. */
354 break;
355 }
356 break;
357
358 default:
359 /* Unsupported. */
360 break;
361 }
362
363 /* Requested object is unknown or invalid. */
364 if (master_template == NULL)
365 return (CKR_ATTRIBUTE_VALUE_INVALID);
366 else {
367 *attributes = master_template;
368 *num_attributes = master_template_size;
369 return (CKR_OK);
370 }
371 }
372
373
374 /*
375 * get_master_attributes_by_type
376 *
377 * Returns an (statically allocated) set of object attributes, as determined by
378 * the specified class and subtype. The attributes are initialized to default
379 * values.
380 */
381 CK_RV
382 get_master_attributes_by_type(CK_OBJECT_CLASS class, CK_ULONG subtype,
383 generic_attr_t **attributes, size_t *num_attributes)
384 {
385 CK_RV rv;
386 generic_attr_t *master_template = NULL;
387 generic_attr_t *new_attributes;
388 size_t i, num_new_attributes, master_template_size = 0;
389
390 /* Determine the appropriate master template needed. */
391 rv = get_master_template_by_type(class, subtype,
392 &master_template, &master_template_size);
393 if (rv != CKR_OK)
394 return (rv);
395
396 /* Duplicate the master template. */
397 new_attributes = malloc(master_template_size);
398 if (new_attributes == NULL)
399 return (CKR_HOST_MEMORY);
400
401 (void) memcpy(new_attributes, master_template, master_template_size);
402 num_new_attributes = master_template_size / sizeof (generic_attr_t);
403
404 /* Set the pointer in the appropriate storage area. */
405 for (i = 0; i < num_new_attributes; i++) {
406 generic_attr_t *attr;
407
408 attr = new_attributes + i;
409
410 switch (attr->attribute.ulValueLen) {
411 case (sizeof (CK_ULONG)):
412 attr->attribute.pValue = &attr->generic_ulong;
413 break;
414 case (sizeof (CK_BBOOL)):
415 attr->attribute.pValue = &attr->generic_bbool;
416 break;
417 default:
418 attr->attribute.pValue = attr->generic_data;
419 break;
420 }
421
422 }
423
424 /* Secret keys share a common template, so set the key type here. */
425 if (class == CKO_SECRET_KEY) {
426 /* Keytype / subtype is always the second attribute. */
427 new_attributes[1].generic_ulong = subtype;
428 }
429
430 *attributes = new_attributes;
431 *num_attributes = num_new_attributes;
432
433 return (CKR_OK);
434 }
435
436
437 /*
438 * get_master_attributes_by_duplication
439 *
440 * Returns an (statically allocated) set of object attributes, as copied from an
441 * existing set of attributes. The new attributes inherit the values from
442 * the old attributes.
443 */
444 CK_RV
445 get_master_attributes_by_duplication(
446 generic_attr_t *src_attrs, size_t num_src_attrs,
447 generic_attr_t **dst_attrs, size_t *num_dst_attrs)
448 {
449 CK_RV rv = CKR_OK;
450 generic_attr_t *new_attrs, *src, *dst;
451 size_t i;
452
453 new_attrs = malloc(sizeof (generic_attr_t) * num_src_attrs);
454 if (new_attrs == NULL)
455 return (CKR_HOST_MEMORY);
456
457 for (i = 0; i < num_src_attrs; i++) {
458 src = src_attrs + i;
459 dst = new_attrs + i;
460
461 *dst = *src;
462
463 /* Adjust pointers in dst so that they don't point to src. */
464
465 if (src->isMalloced) {
466 dst->attribute.pValue =
467 malloc(src->attribute.ulValueLen);
468
469 if (dst->attribute.pValue == NULL) {
470 /*
471 * Continue on error, so that the cleanup
472 * routine doesn't see pointers to src_attrs.
473 */
474 dst->attribute.ulValueLen = 0;
475 rv = CKR_HOST_MEMORY;
476 continue;
477 }
478 } else if (src->attribute.pValue == &src->generic_bbool) {
479 dst->attribute.pValue = &dst->generic_bbool;
480 } else if (src->attribute.pValue == &src->generic_ulong) {
481 dst->attribute.pValue = &dst->generic_ulong;
482 } else if (src->attribute.pValue == &src->generic_data) {
483 dst->attribute.pValue = &dst->generic_data;
484 } else {
485 /* This shouldn't happen. */
486 dst->attribute.pValue = NULL;
487 dst->attribute.ulValueLen = 0;
488 rv = CKR_GENERAL_ERROR;
489 num_src_attrs = i + 1;
490 break;
491 }
492
493 (void) memcpy(dst->attribute.pValue, src->attribute.pValue,
494 src->attribute.ulValueLen);
495 }
496
497 if (rv != CKR_OK) {
498 dealloc_attributes(new_attrs, num_src_attrs);
499 } else {
500 *dst_attrs = new_attrs;
501 *num_dst_attrs = num_src_attrs;
502 }
503
504 return (rv);
505 }
506
507
508 /*
509 * dealloc_attributes
510 *
511 * Deallocates the storage used for a set of attributes. The attribute
512 * values are zeroed out before being free'd.
513 */
514 void
515 dealloc_attributes(generic_attr_t *attributes, size_t num_attributes)
516 {
517 size_t i;
518 generic_attr_t *attr;
519
520 for (i = 0; i < num_attributes; i++) {
521 attr = attributes + i;
522
523 /*
524 * Zero-out any attribute values. We could do this just for
525 * attributes with isSensitive == True, but it's not much
526 * extra work to just do them all. [Most attributes are just
527 * 1 or 4 bytes]
528 */
529 bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
530
531 if (attr->isMalloced)
532 free(attr->attribute.pValue);
533 }
534
535 free(attributes);
536 }
537
538
539 /*
540 * attribute_set_value
541 *
542 * Sets the value of the specified attribute. Any portion of the old value
543 * which will not be overwritten by the new value is zeroed out.
544 */
545 CK_RV
546 attribute_set_value(CK_ATTRIBUTE *new_attr,
547 generic_attr_t *attributes, size_t num_attributes)
548 {
549 generic_attr_t *attr = NULL;
550
551 if (new_attr == NULL)
552 return (CKR_TEMPLATE_INCOMPLETE);
553 else if (new_attr->pValue == NULL) {
554 return (CKR_ATTRIBUTE_VALUE_INVALID);
555 }
556
557 find_attribute(new_attr->type, attributes, num_attributes, &attr);
558 if (attr == NULL) {
559 return (CKR_ATTRIBUTE_TYPE_INVALID);
560 }
561
562 /* Store the new value. */
563 if (attr->attribute.ulValueLen >= new_attr->ulValueLen) {
564 /* Existing storage is sufficient to store new value. */
565
566 /* bzero() out any data that won't be overwritten. */
567 bzero((char *)attr->attribute.pValue + new_attr->ulValueLen,
568 attr->attribute.ulValueLen - new_attr->ulValueLen);
569
570 } else if (new_attr->ulValueLen <= sizeof (attr->generic_data)) {
571 /* Use generic storage to avoid a malloc. */
572
573 bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
574 if (attr->isMalloced) {
575 /*
576 * If app sets a large value (triggering a malloc),
577 * then sets a tiny value, and finally again sets
578 * a large value (phew!) we could end up here.
579 *
580 * FUTURE?: Store the original malloc size, so that
581 * we can regrow the value up to the original size.
582 * This might avoid some heap churn for pathalogic
583 * applications.
584 */
585 free(attr->attribute.pValue);
586 attr->isMalloced = B_FALSE;
587 }
588
589 attr->attribute.pValue = attr->generic_data;
590
591 } else {
592 /* Need to allocate storage for the new value. */
593 void *newStorage;
594
595 newStorage = malloc(new_attr->ulValueLen);
596 if (newStorage == NULL)
597 return (CKR_HOST_MEMORY);
598 bzero(attr->attribute.pValue, attr->attribute.ulValueLen);
599 attr->attribute.pValue = newStorage;
600 attr->isMalloced = B_TRUE;
601 }
602
603 (void) memcpy(attr->attribute.pValue, new_attr->pValue,
604 new_attr->ulValueLen);
605 attr->attribute.ulValueLen = new_attr->ulValueLen;
606 attr->hasValueForClone = B_TRUE;
607
608 return (CKR_OK);
609 }
610
611
612 /*
613 * find_attribute
614 *
615 * Passes a pointer to the requested attribute, or NULL if not found.
616 */
617 static void
618 find_attribute(CK_ATTRIBUTE_TYPE attrtype, generic_attr_t *attributes,
619 size_t num_attributes, generic_attr_t **found_attribute)
620 {
621 generic_attr_t *attr;
622 boolean_t found = B_FALSE;
623 size_t i;
624
625 /* Find the requested attribute. */
626 for (i = 0, attr = attributes; i < num_attributes; i++, attr++) {
627 if (attr->attribute.type == attrtype) {
628 found = B_TRUE;
629 break;
630 }
631 }
632
633 *found_attribute = found ? attr : NULL;
634 }
635
636
637 /*
638 * get_template_ulong
639 *
640 * Look for the specified ulong-size attribute, and retrieve its value. The
641 * return value specifies if the attribute was found (or not).
642 */
643 boolean_t
644 get_template_ulong(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
645 CK_ULONG num_attributes, CK_ULONG *result)
646 {
647 boolean_t found = B_FALSE;
648 CK_ULONG i;
649
650 for (i = 0; i < num_attributes; i++) {
651 if (attributes[i].type == type) {
652 CK_ULONG *value = attributes[i].pValue;
653
654 *result = *value;
655 found = B_TRUE;
656 break;
657 }
658 }
659
660 return (found);
661 }
662
663
664 /*
665 * get_template_boolean
666 *
667 * Look for the specified boolean attribute, and retrieve its value. The
668 * return value specifies if the attribute was found (or not).
669 */
670 boolean_t
671 get_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
672 CK_ULONG num_attributes, boolean_t *result)
673 {
674 boolean_t found = B_FALSE;
675 CK_ULONG i;
676
677 for (i = 0; i < num_attributes; i++) {
678 if (attributes[i].type == type) {
679 CK_BBOOL *value = attributes[i].pValue;
680
681 if (*value == CK_FALSE)
682 *result = B_FALSE;
683 else
684 *result = B_TRUE;
685
686 found = B_TRUE;
687 break;
688 }
689 }
690
691 return (found);
692 }
693
694 /*
695 * set_template_boolean
696 *
697 * Look for the specified boolean attribute, and set its value.
698 *
699 * if 'local' is true, it sets the pointer to the value in the template a new
700 * location. There should be no memory leak created by this because we are
701 * only doing this to booleans which should not be malloc'ed.
702 *
703 * if 'local' is false, it sets its value.
704 *
705 * The return value specifies if the attribute was found (or not).
706 */
707 int
708 set_template_boolean(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE *attributes,
709 CK_ULONG num_attributes, boolean_t local, CK_BBOOL *value)
710 {
711 int i;
712
713 for (i = 0; i < num_attributes; i++) {
714 if (attributes[i].type == type) {
715 if (local)
716 attributes[i].pValue = value;
717 else
718 *((CK_BBOOL *)attributes[i].pValue) = *value;
719
720 return (i);
721 }
722 }
723
724 return (-1);
725 }