1 /*
2  *		Common Public License Version 0.5
3  *
4  *		THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF
5  *		THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE,
6  *		REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
7  *		RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
8  *
9  *		1. DEFINITIONS
10  *
11  *		"Contribution" means:
12  *		      a) in the case of the initial Contributor, the
13  *		      initial code and documentation distributed under
14  *		      this Agreement, and
15  *
16  *		      b) in the case of each subsequent Contributor:
17  *		      i) changes to the Program, and
18  *		      ii) additions to the Program;
19  *
20  *		      where such changes and/or additions to the Program
21  *		      originate from and are distributed by that
22  *		      particular Contributor. A Contribution 'originates'
23  *		      from a Contributor if it was added to the Program
24  *		      by such Contributor itself or anyone acting on such
25  *		      Contributor's behalf. Contributions do not include
26  *		      additions to the Program which: (i) are separate
27  *		      modules of software distributed in conjunction with
28  *		      the Program under their own license agreement, and
29  *		      (ii) are not derivative works of the Program.
30  *
31  *
32  *		"Contributor" means any person or entity that distributes
33  *		the Program.
34  *
35  *		"Licensed Patents " mean patent claims licensable by a
36  *		Contributor which are necessarily infringed by the use or
37  *		sale of its Contribution alone or when combined with the
38  *		Program.
39  *
40  *		"Program" means the Contributions distributed in
41  *		accordance with this Agreement.
42  *
43  *		"Recipient" means anyone who receives the Program under
44  *		this Agreement, including all Contributors.
45  *
46  *		2. GRANT OF RIGHTS
47  *
48  *		      a) Subject to the terms of this Agreement, each
49  *		      Contributor hereby grants Recipient a
50  *		      no - exclusive, worldwide, royalt - free copyright
51  *		      license to reproduce, prepare derivative works of,
52  *		      publicly display, publicly perform, distribute and
53  *		      sublicense the Contribution of such Contributor, if
54  *		      any, and such derivative works, in source code and
55  *		      object code form.
56  *
57  *		      b) Subject to the terms of this Agreement, each
58  *		      Contributor hereby grants Recipient a
59  *		      no - exclusive, worldwide, royalt - free patent
60  *		      license under Licensed Patents to make, use, sell,
61  *		      offer to sell, import and otherwise transfer the
62  *		      Contribution of such Contributor, if any, in source
63  *		      code and object code form. This patent license
64  *		      shall apply to the combination of the Contribution
65  *		      and the Program if, at the time the Contribution is
66  *		      added by the Contributor, such addition of the
67  *		      Contribution causes such combination to be covered
68  *		      by the Licensed Patents. The patent license shall
69  *		      not apply to any other combinations which include
70  *		      the Contribution. No hardware per se is licensed
71  *		      hereunder.
72  *
73  *		      c) Recipient understands that although each
74  *		      Contributor grants the licenses to its
75  *		      Contributions set forth herein, no assurances are
76  *		      provided by any Contributor that the Program does
77  *		      not infringe the patent or other intellectual
78  *		      property rights of any other entity. Each
79  *		      Contributor disclaims any liability to Recipient
80  *		      for claims brought by any other entity based on
81  *		      infringement of intellectual property rights or
82  *		      otherwise. As a condition to exercising the rights
83  *		      and licenses granted hereunder, each Recipient
84  *		      hereby assumes sole responsibility to secure any
85  *		      other intellectual property rights needed, if any.
86  *
87  *		      For example, if a third party patent license is
88  *		      required to allow Recipient to distribute the
89  *		      Program, it is Recipient's responsibility to
90  *		      acquire that license before distributing the
91  *		      Program.
92  *
93  *		      d) Each Contributor represents that to its
94  *		      knowledge it has sufficient copyright rights in its
95  *		      Contribution, if any, to grant the copyright
96  *		      license set forth in this Agreement.
97  *
98  *		3. REQUIREMENTS
99  *
100  *		A Contributor may choose to distribute the Program in
101  *		object code form under its own license agreement, provided
102  *		that:
103  *		      a) it complies with the terms and conditions of
104  *		      this Agreement; and
105  *
106  *		      b) its license agreement:
107  *		      i) effectively disclaims on behalf of all
108  *		      Contributors all warranties and conditions, express
109  *		      and implied, including warranties or conditions of
110  *		      title and no - infringement, and implied warranties
111  *		      or conditions of merchantability and fitness for a
112  *		      particular purpose;
113  *
114  *		      ii) effectively excludes on behalf of all
115  *		      Contributors all liability for damages, including
116  *		      direct, indirect, special, incidental and
117  *		      consequential damages, such as lost profits;
118  *
119  *		      iii) states that any provisions which differ from
120  *		      this Agreement are offered by that Contributor
121  *		      alone and not by any other party; and
122  *
123  *		      iv) states that source code for the Program is
124  *		      available from such Contributor, and informs
125  *		      licensees how to obtain it in a reasonable manner
126  *		      on or through a medium customarily used for
127  *		      software exchange.
128  *
129  *		When the Program is made available in source code form:
130  *		      a) it must be made available under this Agreement;
131  *		      and
132  *		      b) a copy of this Agreement must be included with
133  *		      each copy of the Program.
134  *
135  *		Contributors may not remove or alter any copyright notices
136  *		contained within the Program.
137  *
138  *		Each Contributor must identify itself as the originator of
139  *		its Contribution, if any, in a manner that reasonably
140  *		allows subsequent Recipients to identify the originator of
141  *		the Contribution.
142  *
143  *
144  *		4. COMMERCIAL DISTRIBUTION
145  *
146  *		Commercial distributors of software may accept certain
147  *		responsibilities with respect to end users, business
148  *		partners and the like. While this license is intended to
149  *		facilitate the commercial use of the Program, the
150  *		Contributor who includes the Program in a commercial
151  *		product offering should do so in a manner which does not
152  *		create potential liability for other Contributors.
153  *		Therefore, if a Contributor includes the Program in a
154  *		commercial product offering, such Contributor ("Commercial
155  *		Contributor") hereby agrees to defend and indemnify every
156  *		other Contributor ("Indemnified Contributor") against any
157  *		losses, damages and costs (collectively "Losses") arising
158  *		from claims, lawsuits and other legal actions brought by a
159  *		third party against the Indemnified Contributor to the
160  *		extent caused by the acts or omissions of such Commercial
161  *		Contributor in connection with its distribution of the
162  *		Program in a commercial product offering. The obligations
163  *		in this section do not apply to any claims or Losses
164  *		relating to any actual or alleged intellectual property
165  *		infringement. In order to qualify, an Indemnified
166  *		Contributor must: a) promptly notify the Commercial
167  *		Contributor in writing of such claim, and b) allow the
168  *		Commercial Contributor to control, and cooperate with the
169  *		Commercial Contributor in, the defense and any related
170  *		settlement negotiations. The Indemnified Contributor may
171  *		participate in any such claim at its own expense.
172  *
173  *
174  *		For example, a Contributor might include the Program in a
175  *		commercial product offering, Product X. That Contributor
176  *		is then a Commercial Contributor. If that Commercial
177  *		Contributor then makes performance claims, or offers
178  *		warranties related to Product X, those performance claims
179  *		and warranties are such Commercial Contributor's
180  *		responsibility alone. Under this section, the Commercial
181  *		Contributor would have to defend claims against the other
182  *		Contributors related to those performance claims and
183  *		warranties, and if a court requires any other Contributor
184  *		to pay any damages as a result, the Commercial Contributor
185  *		must pay those damages.
186  *
187  *
188  *		5. NO WARRANTY
189  *
190  *		EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE
191  *		PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
192  *		WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
193  *		IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
194  *		CONDITIONS OF TITLE, NO - INFRINGEMENT, MERCHANTABILITY OR
195  *		FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
196  *		responsible for determining the appropriateness of using
197  *		and distributing the Program and assumes all risks
198  *		associated with its exercise of rights under this
199  *		Agreement, including but not limited to the risks and
200  *		costs of program errors, compliance with applicable laws,
201  *		damage to or loss of data, programs or equipment, and
202  *		unavailability or interruption of operations.
203  *
204  *		6. DISCLAIMER OF LIABILITY
205  *		EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER
206  *		RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY
207  *		FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
208  *		OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
209  *		LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
210  *		LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
211  *		(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
212  *		OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE
213  *		OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
214  *		POSSIBILITY OF SUCH DAMAGES.
215  *
216  *		7. GENERAL
217  *
218  *		If any provision of this Agreement is invalid or
219  *		unenforceable under applicable law, it shall not affect
220  *		the validity or enforceability of the remainder of the
221  *		terms of this Agreement, and without further action by the
222  *		parties hereto, such provision shall be reformed to the
223  *		minimum extent necessary to make such provision valid and
224  *		enforceable.
225  *
226  *
227  *		If Recipient institutes patent litigation against a
228  *		Contributor with respect to a patent applicable to
229  *		software (including a cros - claim or counterclaim in a
230  *		lawsuit), then any patent licenses granted by that
231  *		Contributor to such Recipient under this Agreement shall
232  *		terminate as of the date such litigation is filed. In
233  *		addition, If Recipient institutes patent litigation
234  *		against any entity (including a cros - claim or
235  *		counterclaim in a lawsuit) alleging that the Program
236  *		itself (excluding combinations of the Program with other
237  *		software or hardware) infringes such Recipient's
238  *		patent(s), then such Recipient's rights granted under
239  *		Section 2(b) shall terminate as of the date such
240  *		litigation is filed.
241  *
242  *		All Recipient's rights under this Agreement shall
243  *		terminate if it fails to comply with any of the material
244  *		terms or conditions of this Agreement and does not cure
245  *		such failure in a reasonable period of time after becoming
246  *		aware of such noncompliance. If all Recipient's rights
247  *		under this Agreement terminate, Recipient agrees to cease
248  *		use and distribution of the Program as soon as reasonably
249  *		practicable. However, Recipient's obligations under this
250  *		Agreement and any licenses granted by Recipient relating
251  *		to the Program shall continue and survive.
252  *
253  *		Everyone is permitted to copy and distribute copies of
254  *		this Agreement, but in order to avoid inconsistency the
255  *		Agreement is copyrighted and may only be modified in the
256  *		following manner. The Agreement Steward reserves the right
257  *		to publish new versions (including revisions) of this
258  *		Agreement from time to time. No one other than the
259  *		Agreement Steward has the right to modify this Agreement.
260  *
261  *		IBM is the initial Agreement Steward. IBM may assign the
262  *		responsibility to serve as the Agreement Steward to a
263  *		suitable separate entity. Each new version of the
264  *		Agreement will be given a distinguishing version number.
265  *		The Program (including Contributions) may always be
266  *		distributed subject to the version of the Agreement under
267  *		which it was received. In addition, after a new version of
268  *		the Agreement is published, Contributor may elect to
269  *		distribute the Program (including its Contributions) under
270  *		the new version. Except as expressly stated in Sections
271  *		2(a) and 2(b) above, Recipient receives no rights or
272  *		licenses to the intellectual property of any Contributor
273  *		under this Agreement, whether expressly, by implication,
274  *		estoppel or otherwise. All rights in the Program not
275  *		expressly granted under this Agreement are reserved.
276  *
277  *
278  *		This Agreement is governed by the laws of the State of New
279  *		York and the intellectual property laws of the United
280  *		States of America. No party to this Agreement will bring a
281  *		legal action under this Agreement more than one year after
282  *		the cause of action arose. Each party waives its rights to
283  *		a jury trial in any resulting litigation.
284  *
285  *
286  *
287  * (C) COPYRIGHT International Business Machines Corp. 2001, 2002
288  */
289 /*
290  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
291  * Use is subject to license terms.
292  */
293 
294 #include "tpmtok_int.h"
295 
296 // template_add_attributes()
297 //
298 // blindly add the given attributes to the template.  do no sanity checking
299 // at this point.  sanity checking will occur later.
300 //
301 CK_RV
template_add_attributes(TEMPLATE * tmpl,CK_ATTRIBUTE * pTemplate,CK_ULONG ulCount)302 template_add_attributes(TEMPLATE	* tmpl,
303 	CK_ATTRIBUTE * pTemplate,
304 	CK_ULONG	ulCount)
305 {
306 	CK_ATTRIBUTE  * attr = NULL;
307 	CK_RV	   rc;
308 	unsigned int    i;
309 
310 	for (i = 0; i < ulCount; i++) {
311 		if (! is_attribute_defined(pTemplate[i].type)) {
312 			return (CKR_ATTRIBUTE_TYPE_INVALID);
313 		}
314 		attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) +
315 		    pTemplate[i].ulValueLen);
316 		if (! attr) {
317 			return (CKR_HOST_MEMORY);
318 		}
319 		attr->type	= pTemplate[i].type;
320 		attr->ulValueLen = pTemplate[i].ulValueLen;
321 
322 		if (attr->ulValueLen != 0) {
323 			attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE);
324 			(void) memcpy(attr->pValue, pTemplate[i].pValue,
325 			    attr->ulValueLen);
326 		} else
327 			attr->pValue = NULL;
328 
329 		rc = template_update_attribute(tmpl, attr);
330 		if (rc != CKR_OK) {
331 			free(attr);
332 			return (rc);
333 		}
334 	}
335 
336 	return (CKR_OK);
337 }
338 
339 
340 // template_add_default_attributes()
341 //
342 CK_RV
template_add_default_attributes(TEMPLATE * tmpl,CK_ULONG class,CK_ULONG subclass,CK_ULONG mode)343 template_add_default_attributes(TEMPLATE * tmpl,
344 	CK_ULONG   class,
345 	CK_ULONG   subclass,
346 	CK_ULONG   mode)
347 {
348 	CK_RV rc;
349 
350 	// first add the default common attributes
351 	//
352 	rc = template_set_default_common_attributes(tmpl);
353 	if (rc != CKR_OK) {
354 		return (rc);
355 	}
356 	// set the template class - specific default attributes
357 	//
358 	switch (class) {
359 		case CKO_DATA:
360 		return (data_object_set_default_attributes(tmpl, mode));
361 		case CKO_CERTIFICATE:
362 		if (subclass == CKC_X_509)
363 			return (cert_x509_set_default_attributes(tmpl, mode));
364 		else
365 			return (CKR_OK);
366 		case CKO_PUBLIC_KEY:
367 		switch (subclass) {
368 			case CKK_RSA:
369 				return (rsa_publ_set_default_attributes(
370 				    tmpl, mode));
371 			default:
372 				return (CKR_ATTRIBUTE_VALUE_INVALID);
373 		}
374 
375 		case CKO_PRIVATE_KEY:
376 		switch (subclass) {
377 			case CKK_RSA:
378 				return (rsa_priv_set_default_attributes(
379 				    tmpl, mode));
380 			default:
381 				return (CKR_ATTRIBUTE_VALUE_INVALID);
382 		}
383 
384 		case CKO_SECRET_KEY:
385 		switch (subclass) {
386 			case CKK_GENERIC_SECRET:
387 				return (generic_secret_set_default_attributes(
388 				    tmpl, mode));
389 			default:
390 				return (CKR_ATTRIBUTE_VALUE_INVALID);
391 		}
392 
393 		case CKO_HW_FEATURE:
394 		switch (subclass) {
395 			case CKH_CLOCK:
396 				return (clock_set_default_attributes(
397 				    tmpl));
398 			case CKH_MONOTONIC_COUNTER:
399 				return (counter_set_default_attributes(
400 				    tmpl));
401 			default:
402 				return (CKR_ATTRIBUTE_VALUE_INVALID);
403 		}
404 
405 		case CKO_DOMAIN_PARAMETERS:
406 		switch (subclass) {
407 			default:
408 				return (CKR_ATTRIBUTE_VALUE_INVALID);
409 		}
410 
411 		default:
412 			return (CKR_ATTRIBUTE_VALUE_INVALID);
413 	}
414 }
415 
416 // template_attribute_find()
417 //
418 // find the attribute in the list and return (its value
419 //
420 CK_BBOOL
template_attribute_find(TEMPLATE * tmpl,CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE ** attr)421 template_attribute_find(TEMPLATE	   * tmpl,
422 	CK_ATTRIBUTE_TYPE    type,
423 	CK_ATTRIBUTE	** attr)
424 {
425 	DL_NODE	* node = NULL;
426 	CK_ATTRIBUTE * a    = NULL;
427 
428 	if (! tmpl || ! attr)
429 		return (FALSE);
430 	node = tmpl->attribute_list;
431 
432 	while (node != NULL) {
433 		a = (CK_ATTRIBUTE *)node->data;
434 
435 		if (type == a->type) {
436 			*attr = a;
437 			return (TRUE);
438 		}
439 
440 		node = node->next;
441 	}
442 
443 	*attr = NULL;
444 	return (FALSE);
445 }
446 
447 // template_attribute_find_multiple()
448 //
449 // find the attributes in the list and return (their values
450 //
451 void
template_attribute_find_multiple(TEMPLATE * tmpl,ATTRIBUTE_PARSE_LIST * parselist,CK_ULONG plcount)452 template_attribute_find_multiple(TEMPLATE		* tmpl,
453 	ATTRIBUTE_PARSE_LIST * parselist,
454 	CK_ULONG		plcount)
455 {
456 	CK_ATTRIBUTE  * attr = NULL;
457 	CK_ULONG	i;
458 
459 	for (i = 0; i < plcount; i++) {
460 		parselist[i].found = template_attribute_find(
461 		    tmpl, parselist[i].type, &attr);
462 
463 		if (parselist[i].found && parselist[i].ptr != NULL)
464 			(void) memcpy(parselist[i].ptr, attr->pValue,
465 			    parselist[i].len);
466 	}
467 }
468 
469 CK_RV
template_check_required_attributes(TEMPLATE * tmpl,CK_ULONG class,CK_ULONG subclass,CK_ULONG mode)470 template_check_required_attributes(TEMPLATE  * tmpl,
471 	CK_ULONG    class,
472 	CK_ULONG    subclass,
473 	CK_ULONG    mode)
474 {
475 	if (class == CKO_DATA)
476 		return (data_object_check_required_attributes(
477 		    tmpl, mode));
478 	else if (class == CKO_CERTIFICATE) {
479 		if (subclass == CKC_X_509)
480 			return (cert_x509_check_required_attributes(
481 			    tmpl, mode));
482 		else
483 			return (cert_vendor_check_required_attributes(
484 			    tmpl, mode));
485 	} else if (class == CKO_PUBLIC_KEY) {
486 		switch (subclass) {
487 			case CKK_RSA:
488 				return (rsa_publ_check_required_attributes(
489 				    tmpl, mode));
490 			default:
491 				return (CKR_ATTRIBUTE_VALUE_INVALID);
492 		}
493 	} else if (class == CKO_PRIVATE_KEY) {
494 		switch (subclass) {
495 			case CKK_RSA:
496 				return (rsa_priv_check_required_attributes(
497 				    tmpl, mode));
498 			default:
499 				return (CKR_ATTRIBUTE_VALUE_INVALID);
500 		}
501 	} else if (class == CKO_SECRET_KEY) {
502 		switch (subclass) {
503 			case CKK_GENERIC_SECRET:
504 				return (
505 				    generic_secret_check_required_attributes(
506 				    tmpl, mode));
507 			default:
508 				return (CKR_ATTRIBUTE_VALUE_INVALID);
509 		}
510 	} else if (class == CKO_HW_FEATURE) {
511 
512 		switch (subclass) {
513 			case CKH_CLOCK:
514 				return (
515 				    clock_check_required_attributes(
516 				    tmpl, mode));
517 			case CKH_MONOTONIC_COUNTER:
518 				return (
519 				    counter_check_required_attributes(
520 				    tmpl, mode));
521 			default:
522 				return (CKR_ATTRIBUTE_VALUE_INVALID);
523 		}
524 	} else if (class == CKO_DOMAIN_PARAMETERS) {
525 		switch (subclass) {
526 			default:
527 				return (CKR_ATTRIBUTE_VALUE_INVALID);
528 		}
529 	}
530 	return (CKR_ATTRIBUTE_VALUE_INVALID);
531 }
532 
533 
534 // template_check_required_base_attributes()
535 //
536 // check to make sure that attributes required by Cryptoki are
537 // present.  does not check to see if the attribute makes sense
538 // for the particular object (that is done in the 'validate' routines)
539 //
540 CK_RV
template_check_required_base_attributes(TEMPLATE * tmpl,CK_ULONG mode)541 template_check_required_base_attributes(TEMPLATE * tmpl,
542 CK_ULONG   mode)
543 {
544 	CK_ATTRIBUTE  * attr;
545 	CK_BBOOL	found;
546 
547 	found = template_attribute_find(tmpl, CKA_CLASS, &attr);
548 	if (mode == MODE_CREATE && found == FALSE)
549 		return (CKR_TEMPLATE_INCOMPLETE);
550 	return (CKR_OK);
551 }
552 
553 
554 // template_compare()
555 //
556 CK_BBOOL
template_compare(CK_ATTRIBUTE * t1,CK_ULONG ulCount,TEMPLATE * t2)557 template_compare(CK_ATTRIBUTE  * t1,
558 	CK_ULONG	ulCount,
559 	TEMPLATE	* t2) {
560 	CK_ATTRIBUTE  * attr1 = NULL;
561 	CK_ATTRIBUTE  * attr2 = NULL;
562 	CK_ULONG	i;
563 	CK_RV	   rc;
564 
565 	if (! t1 || ! t2)
566 		return (FALSE);
567 	attr1 = t1;
568 
569 	for (i = 0; i < ulCount; i++) {
570 		rc = template_attribute_find(t2, attr1->type, &attr2);
571 		if (rc == FALSE)
572 			return (FALSE);
573 		if (attr1->ulValueLen != attr2->ulValueLen)
574 			return (FALSE);
575 		if (memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)
576 		    != 0)
577 			return (FALSE);
578 		attr1++;
579 	}
580 
581 	return (TRUE);
582 }
583 
584 // template_copy()
585 //
586 // This doesn't copy the template items verbatim.  The new template is in
587 // the reverse order of the old one.  This should not have any effect.
588 //
589 // This is very similar to template_merge().  template_merge() can also
590 // be used to copy a list (of unique attributes) but is slower because for
591 // each attribute, it must search through the list.
592 //
593 CK_RV
template_copy(TEMPLATE * dest,TEMPLATE * src)594 template_copy(TEMPLATE *dest, TEMPLATE *src) {
595 	DL_NODE  *node;
596 
597 	if (! dest || ! src) {
598 		return (CKR_FUNCTION_FAILED);
599 	}
600 	node = src->attribute_list;
601 
602 	while (node) {
603 		CK_ATTRIBUTE *attr	= (CK_ATTRIBUTE *)node->data;
604 		CK_ATTRIBUTE *new_attr = NULL;
605 		CK_ULONG	len;
606 
607 		len = sizeof (CK_ATTRIBUTE) + attr->ulValueLen;
608 
609 		new_attr = (CK_ATTRIBUTE *)malloc(len);
610 		if (! new_attr) {
611 			return (CKR_HOST_MEMORY);
612 		}
613 		(void) memcpy(new_attr, attr, len);
614 
615 		new_attr->pValue = (CK_BYTE *)new_attr + sizeof (CK_ATTRIBUTE);
616 
617 		dest->attribute_list = dlist_add_as_first(dest->attribute_list,
618 		    new_attr);
619 
620 		node = node->next;
621 	}
622 
623 	return (CKR_OK);
624 }
625 
626 
627 // template_flatten() - this still gets used when saving token objects to disk
628 //
629 CK_RV
template_flatten(TEMPLATE * tmpl,CK_BYTE * dest)630 template_flatten(TEMPLATE  * tmpl,
631 	CK_BYTE   * dest)
632 {
633 	DL_NODE   * node = NULL;
634 	CK_BYTE   * ptr = NULL;
635 	CK_ULONG_32 long_len;
636 	CK_ATTRIBUTE_32 *attr_32;
637 	CK_ULONG    Val;
638 	CK_ULONG_32 Val_32;
639 	CK_ULONG  * pVal;
640 	long_len = sizeof (CK_ULONG);
641 
642 	if (! tmpl || ! dest) {
643 		return (CKR_FUNCTION_FAILED);
644 	}
645 	ptr = dest;
646 	node = tmpl->attribute_list;
647 	while (node) {
648 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
649 
650 		if (long_len == 4) {
651 			(void) memcpy(ptr, attr, sizeof (CK_ATTRIBUTE) +
652 			    attr->ulValueLen);
653 			ptr += sizeof (CK_ATTRIBUTE) + attr->ulValueLen;
654 		} else {
655 			attr_32 = malloc(sizeof (CK_ATTRIBUTE_32));
656 			if (! attr_32) {
657 				return (CKR_HOST_MEMORY);
658 			}
659 			attr_32->type = attr->type;
660 			attr_32->pValue = 0x00;
661 			if ((attr->type == CKA_CLASS ||
662 			    attr->type == CKA_KEY_TYPE ||
663 			    attr->type == CKA_MODULUS_BITS ||
664 			    attr->type == CKA_VALUE_BITS ||
665 			    attr->type == CKA_CERTIFICATE_TYPE ||
666 			    attr->type == CKA_VALUE_LEN) &&
667 			    attr->ulValueLen != 0) {
668 
669 				attr_32->ulValueLen = sizeof (CK_ULONG_32);
670 
671 				(void) memcpy(ptr, attr_32,
672 				    sizeof (CK_ATTRIBUTE_32));
673 				ptr += sizeof (CK_ATTRIBUTE_32);
674 
675 				pVal = (CK_ULONG *)attr->pValue;
676 				Val = *pVal;
677 				Val_32 = (CK_ULONG_32)Val;
678 				(void) memcpy(ptr, &Val_32,
679 				    sizeof (CK_ULONG_32));
680 				ptr += sizeof (CK_ULONG_32);
681 			} else {
682 				attr_32->ulValueLen = attr->ulValueLen;
683 				(void) memcpy(ptr, attr_32,
684 				    sizeof (CK_ATTRIBUTE_32));
685 				ptr += sizeof (CK_ATTRIBUTE_32);
686 				if (attr->ulValueLen != 0) {
687 					(void) memcpy(ptr, attr->pValue,
688 					    attr->ulValueLen);
689 					ptr += attr->ulValueLen;
690 				}
691 			}
692 			free(attr_32);
693 		}
694 		node = node->next;
695 	}
696 
697 	return (CKR_OK);
698 }
699 
700 CK_RV
template_unflatten(TEMPLATE ** new_tmpl,CK_BYTE * buf,CK_ULONG count)701 template_unflatten(TEMPLATE ** new_tmpl,
702 	CK_BYTE   * buf,
703 	CK_ULONG    count)
704 {
705 	TEMPLATE	* tmpl = NULL;
706 	CK_ATTRIBUTE  * a2   = NULL;
707 	CK_BYTE	*ptr  = NULL;
708 	CK_ULONG	i, len;
709 	CK_RV	   rc;
710 	CK_ULONG_32	long_len = sizeof (CK_ULONG);
711 	CK_ULONG_32	attr_ulong_32;
712 	CK_ULONG	attr_ulong;
713 	CK_ATTRIBUTE * a1_64 = NULL;
714 	CK_ATTRIBUTE_32 * a1 = NULL;
715 
716 	if (! new_tmpl || ! buf) {
717 		return (CKR_FUNCTION_FAILED);
718 	}
719 	tmpl = (TEMPLATE *)malloc(sizeof (TEMPLATE));
720 	if (! tmpl) {
721 		return (CKR_HOST_MEMORY);
722 	}
723 	(void) memset(tmpl, 0x0, sizeof (TEMPLATE));
724 
725 	ptr = buf;
726 	for (i = 0; i < count; i++) {
727 		if (long_len == 4) {
728 			void *aptr = ptr;
729 			a1_64 = (CK_ATTRIBUTE *)aptr;
730 
731 			len = sizeof (CK_ATTRIBUTE) + a1_64->ulValueLen;
732 			a2 = (CK_ATTRIBUTE *)malloc(len);
733 			if (! a2) {
734 				(void) template_free(tmpl);
735 				return (CKR_HOST_MEMORY);
736 			}
737 
738 			(void) memcpy(a2, a1_64, len);
739 		} else {
740 			void *aptr = ptr;
741 			a1 = (CK_ATTRIBUTE_32 *)aptr;
742 
743 			if ((a1->type == CKA_CLASS ||
744 			    a1->type == CKA_KEY_TYPE ||
745 			    a1->type == CKA_MODULUS_BITS ||
746 			    a1->type == CKA_VALUE_BITS ||
747 			    a1->type == CKA_CERTIFICATE_TYPE ||
748 			    a1->type == CKA_VALUE_LEN) &&
749 			    a1->ulValueLen != 0) {
750 				len = sizeof (CK_ATTRIBUTE) + sizeof (CK_ULONG);
751 			} else {
752 				len = sizeof (CK_ATTRIBUTE) + a1->ulValueLen;
753 			}
754 
755 			a2 = (CK_ATTRIBUTE *)malloc(len);
756 			if (! a2) {
757 				return (CKR_HOST_MEMORY);
758 			}
759 			a2->type = a1->type;
760 
761 			if ((a1->type == CKA_CLASS ||
762 			    a1->type == CKA_KEY_TYPE ||
763 			    a1->type == CKA_MODULUS_BITS ||
764 			    a1->type == CKA_VALUE_BITS ||
765 			    a1->type == CKA_CERTIFICATE_TYPE ||
766 			    a1->type == CKA_VALUE_LEN) &&
767 			    a1->ulValueLen != 0) {
768 				a2->ulValueLen = sizeof (CK_ULONG);
769 				{
770 					CK_ULONG_32 *p32;
771 					CK_BYTE *pb2;
772 					void *aptr = a1;
773 					void *bptr;
774 
775 					pb2 = (CK_BYTE *)aptr;
776 					pb2 += sizeof (CK_ATTRIBUTE_32);
777 					bptr = pb2;
778 					p32 = (CK_ULONG_32 *)bptr;
779 					attr_ulong_32 = *p32;
780 				}
781 
782 				attr_ulong = attr_ulong_32;
783 
784 				{
785 					CK_BYTE *pb2;
786 					pb2 = (CK_BYTE *)a2;
787 					pb2 += sizeof (CK_ATTRIBUTE);
788 					(void) memcpy(pb2,
789 					    (CK_BYTE *)&attr_ulong,
790 					    sizeof (CK_ULONG));
791 				}
792 			} else {
793 				CK_BYTE *pb2, *pb;
794 
795 				a2->ulValueLen = a1->ulValueLen;
796 				pb2 = (CK_BYTE *)a2;
797 				pb2 += sizeof (CK_ATTRIBUTE);
798 				pb = (CK_BYTE *)a1;
799 				pb += sizeof (CK_ATTRIBUTE_32);
800 				(void) memcpy(pb2, pb, a1->ulValueLen);
801 			}
802 		}
803 
804 
805 		if (a2->ulValueLen != 0)
806 			a2->pValue = (CK_BYTE *)a2 + sizeof (CK_ATTRIBUTE);
807 		else
808 			a2->pValue = NULL;
809 
810 		rc = template_update_attribute(tmpl, a2);
811 		if (rc != CKR_OK) {
812 			free(a2);
813 			(void) template_free(tmpl);
814 			return (rc);
815 		}
816 		if (long_len == 4)
817 			ptr += len;
818 		else
819 			ptr += sizeof (CK_ATTRIBUTE_32) + a1->ulValueLen;
820 
821 
822 	}
823 
824 		*new_tmpl = tmpl;
825 	return (CKR_OK);
826 }
827 
828 CK_RV
template_free(TEMPLATE * tmpl)829 template_free(TEMPLATE *tmpl) {
830 	if (! tmpl)
831 		return (CKR_OK);
832 	while (tmpl->attribute_list) {
833 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)tmpl->attribute_list->data;
834 
835 		if (attr)
836 			free(attr);
837 
838 		tmpl->attribute_list = dlist_remove_node(tmpl->attribute_list,
839 		tmpl->attribute_list);
840 	}
841 
842 	free(tmpl);
843 	return (CKR_OK);
844 }
845 
846 CK_BBOOL
template_get_class(TEMPLATE * tmpl,CK_ULONG * class,CK_ULONG * subclass)847 template_get_class(TEMPLATE  * tmpl,
848 	CK_ULONG  * class,
849 	CK_ULONG  * subclass)
850 {
851 	DL_NODE * node;
852 	CK_BBOOL  found;
853 
854 	if (! tmpl || ! class || ! subclass)
855 		return (FALSE);
856 	node = tmpl->attribute_list;
857 
858 	while (node) {
859 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
860 
861 		if (attr->type == CKA_CLASS) {
862 			*class = *(CK_OBJECT_CLASS *)attr->pValue;
863 			found = TRUE;
864 		}
865 
866 		if (attr->type == CKA_CERTIFICATE_TYPE)
867 			*subclass = *(CK_CERTIFICATE_TYPE *)attr->pValue;
868 
869 		if (attr->type == CKA_KEY_TYPE)
870 			*subclass = *(CK_KEY_TYPE *)attr->pValue;
871 
872 		node = node->next;
873 	}
874 
875 	return (found);
876 }
877 
878 CK_ULONG
template_get_count(TEMPLATE * tmpl)879 template_get_count(TEMPLATE *tmpl)
880 {
881 	if (tmpl == NULL)
882 		return (0);
883 	return (dlist_length(tmpl->attribute_list));
884 }
885 
886 CK_ULONG
template_get_size(TEMPLATE * tmpl)887 template_get_size(TEMPLATE *tmpl)
888 {
889 	DL_NODE   * node;
890 	CK_ULONG    size = 0;
891 
892 	if (tmpl == NULL)
893 		return (0);
894 	node = tmpl->attribute_list;
895 	while (node) {
896 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
897 
898 		size += sizeof (CK_ATTRIBUTE) + attr->ulValueLen;
899 
900 		node = node->next;
901 	}
902 
903 	return (size);
904 }
905 
906 CK_ULONG
template_get_compressed_size(TEMPLATE * tmpl)907 template_get_compressed_size(TEMPLATE *tmpl)
908 {
909 	DL_NODE   * node;
910 	CK_ULONG    size = 0;
911 
912 	if (tmpl == NULL)
913 		return (0);
914 	node = tmpl->attribute_list;
915 	while (node) {
916 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
917 
918 		size += sizeof (CK_ATTRIBUTE_32);
919 		if ((attr->type == CKA_CLASS ||
920 		    attr->type == CKA_KEY_TYPE ||
921 		    attr->type == CKA_MODULUS_BITS ||
922 		    attr->type == CKA_VALUE_BITS ||
923 		    attr->type == CKA_CERTIFICATE_TYPE ||
924 		    attr->type == CKA_VALUE_LEN) &&
925 		    attr->ulValueLen != 0) {
926 			size += sizeof (CK_ULONG_32);
927 		} else {
928 			size += attr->ulValueLen;
929 		}
930 
931 		node = node->next;
932 	}
933 
934 	return (size);
935 }
936 
937 /*
938  * template_is_okay_to_reveal_attribute()
939  *
940  * determines whether the specified CK_ATTRIBUTE_TYPE is allowed to
941  * be leave the card in the clear.  note: the specified template doesn't need
942  * to actually posess an attribute of type 'type'.  The template is
943  * provided mainly to determine the object class and subclass
944  *
945  * this routine is called by C_GetAttributeValue which exports the attributes
946  * in the clear.  this routine is NOT called when wrapping a key.
947  */
948 CK_BBOOL
template_check_exportability(TEMPLATE * tmpl,CK_ATTRIBUTE_TYPE type)949 template_check_exportability(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type)
950 {
951 	CK_ATTRIBUTE * attr = NULL;
952 	CK_ULONG	class;
953 	CK_ULONG	subclass;
954 	CK_BBOOL	val;
955 
956 	if (! tmpl)
957 		return (FALSE);
958 	(void) template_get_class(tmpl, &class, &subclass);
959 
960 	if (class != CKO_PRIVATE_KEY && class != CKO_SECRET_KEY)
961 		return (TRUE);
962 	val = template_attribute_find(tmpl, CKA_SENSITIVE, &attr);
963 	if (val) {
964 		val = *(CK_BBOOL *)attr->pValue;
965 		if (val == FALSE)
966 			return (TRUE);
967 	} else {
968 		return (FALSE);
969 	}
970 
971 	if (class == CKO_PRIVATE_KEY) {
972 		switch (subclass) {
973 			case CKK_RSA:
974 				return (rsa_priv_check_exportability(type));
975 			default:
976 				return (CKR_ATTRIBUTE_VALUE_INVALID);
977 		}
978 	} else if (class == CKO_SECRET_KEY) {
979 		return (secret_key_check_exportability(type));
980 	}
981 
982 	return (CKR_ATTRIBUTE_VALUE_INVALID);
983 }
984 
985 CK_RV
template_merge(TEMPLATE * dest,TEMPLATE ** src)986 template_merge(TEMPLATE *dest, TEMPLATE **src)
987 {
988 	DL_NODE  *node;
989 	CK_RV	rc;
990 
991 	if (! dest || ! src) {
992 		return (CKR_FUNCTION_FAILED);
993 	}
994 	node = (*src)->attribute_list;
995 
996 	while (node) {
997 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
998 
999 		rc = template_update_attribute(dest, attr);
1000 		if (rc != CKR_OK) {
1001 			return (rc);
1002 		}
1003 		node->data = NULL;
1004 		node = node->next;
1005 	}
1006 
1007 	(void) template_free(*src);
1008 	*src = NULL;
1009 
1010 	return (CKR_OK);
1011 }
1012 
1013 /*
1014  * template_set_default_common_attributes()
1015  *
1016  * Set the default attributes common to all objects:
1017  *
1018  *    CKA_TOKEN	:  FALSE
1019  *    CKA_PRIVATE    :  TRUE -- Cryptoki leaves this up to the token to decide
1020  *    CKA_MODIFIABLE :  TRUE
1021  *    CKA_LABEL	:  empty string
1022  */
1023 CK_RV
template_set_default_common_attributes(TEMPLATE * tmpl)1024 template_set_default_common_attributes(TEMPLATE *tmpl)
1025 {
1026 	CK_ATTRIBUTE * token_attr;
1027 	CK_ATTRIBUTE * priv_attr;
1028 	CK_ATTRIBUTE * mod_attr;
1029 	CK_ATTRIBUTE * label_attr;
1030 
1031 	token_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) +
1032 	    sizeof (CK_BBOOL));
1033 	priv_attr  = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) +
1034 	    sizeof (CK_BBOOL));
1035 	mod_attr   = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) +
1036 	    sizeof (CK_BBOOL));
1037 	label_attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + 0);
1038 
1039 	if (! token_attr || ! priv_attr || ! mod_attr || ! label_attr) {
1040 		if (token_attr) free(token_attr);
1041 		if (priv_attr)  free(priv_attr);
1042 		if (mod_attr)   free(mod_attr);
1043 		if (label_attr) free(label_attr);
1044 
1045 		return (CKR_HOST_MEMORY);
1046 	}
1047 
1048 	token_attr->type	 = CKA_TOKEN;
1049 	token_attr->ulValueLen   = sizeof (CK_BBOOL);
1050 	token_attr->pValue	= (CK_BYTE *)token_attr + sizeof (CK_ATTRIBUTE);
1051 	*(CK_BBOOL *)token_attr->pValue = FALSE;
1052 
1053 	priv_attr->type	  = CKA_PRIVATE;
1054 	priv_attr->ulValueLen    = sizeof (CK_BBOOL);
1055 	priv_attr->pValue	= (CK_BYTE *)priv_attr + sizeof (CK_ATTRIBUTE);
1056 	*(CK_BBOOL *)priv_attr->pValue = FALSE;
1057 
1058 	mod_attr->type	   = CKA_MODIFIABLE;
1059 	mod_attr->ulValueLen	= sizeof (CK_BBOOL);
1060 	mod_attr->pValue	 = (CK_BYTE *)mod_attr + sizeof (CK_ATTRIBUTE);
1061 	*(CK_BBOOL *)mod_attr->pValue = TRUE;
1062 
1063 	label_attr->type	 = CKA_LABEL;
1064 	label_attr->ulValueLen   = 0;	 // empty string
1065 	label_attr->pValue	= NULL;
1066 
1067 	(void) template_update_attribute(tmpl, token_attr);
1068 	(void) template_update_attribute(tmpl, priv_attr);
1069 	(void) template_update_attribute(tmpl, mod_attr);
1070 	(void) template_update_attribute(tmpl, label_attr);
1071 
1072 	return (CKR_OK);
1073 }
1074 
1075 CK_RV
template_update_attribute(TEMPLATE * tmpl,CK_ATTRIBUTE * new_attr)1076 template_update_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *new_attr) {
1077 	DL_NODE	* node = NULL;
1078 	CK_ATTRIBUTE * attr = NULL;
1079 
1080 	if (! tmpl || ! new_attr) {
1081 		return (CKR_FUNCTION_FAILED);
1082 	}
1083 	node = tmpl->attribute_list;
1084 
1085 	while (node != NULL) {
1086 		attr = (CK_ATTRIBUTE *)node->data;
1087 
1088 		if (new_attr->type == attr->type) {
1089 			free(attr);
1090 			tmpl->attribute_list = dlist_remove_node(
1091 			    tmpl->attribute_list, node);
1092 			break;
1093 		}
1094 
1095 		node = node->next;
1096 	}
1097 
1098 	tmpl->attribute_list = dlist_add_as_first(
1099 	    tmpl->attribute_list, new_attr);
1100 
1101 	return (CKR_OK);
1102 }
1103 
1104 CK_RV
template_validate_attribute(TEMPLATE * tmpl,CK_ATTRIBUTE * attr,CK_ULONG class,CK_ULONG subclass,CK_ULONG mode)1105 template_validate_attribute(TEMPLATE	* tmpl,
1106 	CK_ATTRIBUTE * attr,
1107 	CK_ULONG	class,
1108 	CK_ULONG	subclass,
1109 	CK_ULONG	mode)
1110 {
1111 	if (class == CKO_DATA)
1112 		return (data_object_validate_attribute(tmpl, attr, mode));
1113 	else if (class == CKO_CERTIFICATE) {
1114 		if (subclass == CKC_X_509)
1115 			return (cert_x509_validate_attribute(tmpl, attr, mode));
1116 		else
1117 			return (cert_vendor_validate_attribute(tmpl,
1118 			    attr, mode));
1119 	} else if (class == CKO_PUBLIC_KEY) {
1120 
1121 		switch (subclass) {
1122 			case CKK_RSA:
1123 				return (rsa_publ_validate_attribute(tmpl,
1124 				    attr, mode));
1125 			default:
1126 				return (CKR_ATTRIBUTE_VALUE_INVALID);
1127 		}
1128 	} else if (class == CKO_PRIVATE_KEY) {
1129 
1130 		switch (subclass) {
1131 			case CKK_RSA:
1132 				return (rsa_priv_validate_attribute(tmpl,
1133 				    attr, mode));
1134 			default:
1135 				return (CKR_ATTRIBUTE_VALUE_INVALID);
1136 		}
1137 	} else if (class == CKO_SECRET_KEY) {
1138 		switch (subclass) {
1139 			case CKK_GENERIC_SECRET:
1140 				return (generic_secret_validate_attribute(tmpl,
1141 				    attr, mode));
1142 			default:
1143 				return (CKR_ATTRIBUTE_VALUE_INVALID);
1144 			}
1145 		} else if (class == CKO_HW_FEATURE) {
1146 
1147 		switch (subclass) {
1148 			case CKH_CLOCK:
1149 				return (clock_validate_attribute(tmpl,
1150 				    attr, mode));
1151 			case CKH_MONOTONIC_COUNTER:
1152 				return (counter_validate_attribute(tmpl,
1153 				    attr, mode));
1154 			default:
1155 				return (CKR_ATTRIBUTE_VALUE_INVALID);
1156 		}
1157 	} else if (class == CKO_DOMAIN_PARAMETERS) {
1158 		switch (subclass) {
1159 			default:
1160 				return (CKR_ATTRIBUTE_VALUE_INVALID);
1161 		}
1162 	}
1163 	return (CKR_ATTRIBUTE_VALUE_INVALID);
1164 }
1165 
1166 CK_RV
template_validate_attributes(TEMPLATE * tmpl,CK_ULONG class,CK_ULONG subclass,CK_ULONG mode)1167 template_validate_attributes(TEMPLATE * tmpl,
1168 	CK_ULONG   class,
1169 	CK_ULONG   subclass,
1170 	CK_ULONG   mode)
1171 {
1172 	DL_NODE	*node;
1173 	CK_RV	rc = CKR_OK;
1174 
1175 	node = tmpl->attribute_list;
1176 
1177 	while (node) {
1178 		CK_ATTRIBUTE *attr = (CK_ATTRIBUTE *)node->data;
1179 
1180 		rc = template_validate_attribute(tmpl, attr, class,
1181 		    subclass, mode);
1182 		if (rc != CKR_OK) {
1183 			return (rc);
1184 		}
1185 		node = node->next;
1186 	}
1187 
1188 	return (CKR_OK);
1189 }
1190 
1191 CK_RV
template_validate_base_attribute(TEMPLATE * tmpl,CK_ATTRIBUTE * attr,CK_ULONG mode)1192 template_validate_base_attribute(TEMPLATE	* tmpl,
1193 	CK_ATTRIBUTE  * attr,
1194 	CK_ULONG	 mode)
1195 {
1196 	if (! tmpl || ! attr) {
1197 		return (CKR_FUNCTION_FAILED);
1198 	}
1199 	switch (attr->type) {
1200 		case CKA_CLASS:
1201 			if ((mode & (MODE_CREATE | MODE_DERIVE |
1202 			    MODE_KEYGEN | MODE_UNWRAP)) != 0)
1203 				return (CKR_OK);
1204 			break;
1205 
1206 		case CKA_TOKEN:
1207 			if ((mode & (MODE_CREATE | MODE_COPY |
1208 			    MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0)
1209 				return (CKR_OK);
1210 			break;
1211 
1212 		case CKA_PRIVATE:
1213 			if ((mode & (MODE_CREATE | MODE_COPY |
1214 			    MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0)
1215 				return (CKR_OK);
1216 			break;
1217 
1218 		case CKA_LABEL:
1219 			return (CKR_OK);
1220 		case CKA_MODIFIABLE:
1221 			if ((mode & (MODE_CREATE | MODE_COPY |
1222 			    MODE_DERIVE | MODE_KEYGEN | MODE_UNWRAP)) != 0)
1223 				return (CKR_OK);
1224 			break;
1225 
1226 		default:
1227 			return (CKR_TEMPLATE_INCONSISTENT);
1228 		}
1229 
1230 	return (CKR_ATTRIBUTE_READ_ONLY);
1231 }
1232