Mercurial > illumos > illumos-gate
comparison usr/src/lib/pkcs11/pkcs11_kms/common/kmsAttributeUtil.c @ 12720:3db6e0082404
PSARC 2010/195 PKCS11 KMS Provider
6944296 Solaris needs a PKCS#11 provider to allow access to KMS keystore functionality
author | Wyllys Ingersoll <Wyllys.Ingersoll@Sun.COM> |
---|---|
date | Mon, 28 Jun 2010 16:04:11 -0700 |
parents | |
children | e5889df1eaac |
comparison
equal
deleted
inserted
replaced
12719:bd9fb35d09c2 | 12720:3db6e0082404 |
---|---|
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 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. | |
22 */ | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <security/cryptoki.h> | |
26 #include <sys/crypto/common.h> | |
27 #include <aes_impl.h> | |
28 #include "kmsGlobal.h" | |
29 #include "kmsObject.h" | |
30 #include "kmsSession.h" | |
31 #include "kmsSlot.h" | |
32 | |
33 /* | |
34 * This attribute table is used by the kms_lookup_attr() | |
35 * to validate the attributes. | |
36 */ | |
37 CK_ATTRIBUTE_TYPE attr_map[] = { | |
38 CKA_PRIVATE, | |
39 CKA_LABEL, | |
40 CKA_APPLICATION, | |
41 CKA_OBJECT_ID, | |
42 CKA_CERTIFICATE_TYPE, | |
43 CKA_ISSUER, | |
44 CKA_SERIAL_NUMBER, | |
45 CKA_AC_ISSUER, | |
46 CKA_OWNER, | |
47 CKA_ATTR_TYPES, | |
48 CKA_SUBJECT, | |
49 CKA_ID, | |
50 CKA_SENSITIVE, | |
51 CKA_START_DATE, | |
52 CKA_END_DATE, | |
53 CKA_MODULUS, | |
54 CKA_MODULUS_BITS, | |
55 CKA_PUBLIC_EXPONENT, | |
56 CKA_PRIVATE_EXPONENT, | |
57 CKA_PRIME_1, | |
58 CKA_PRIME_2, | |
59 CKA_EXPONENT_1, | |
60 CKA_EXPONENT_2, | |
61 CKA_COEFFICIENT, | |
62 CKA_PRIME, | |
63 CKA_SUBPRIME, | |
64 CKA_BASE, | |
65 CKA_EXTRACTABLE, | |
66 CKA_LOCAL, | |
67 CKA_NEVER_EXTRACTABLE, | |
68 CKA_ALWAYS_SENSITIVE, | |
69 CKA_MODIFIABLE, | |
70 CKA_ECDSA_PARAMS, | |
71 CKA_EC_POINT, | |
72 CKA_SECONDARY_AUTH, | |
73 CKA_AUTH_PIN_FLAGS, | |
74 CKA_HW_FEATURE_TYPE, | |
75 CKA_RESET_ON_INIT, | |
76 CKA_HAS_RESET | |
77 }; | |
78 | |
79 /* | |
80 * attributes that exists only in secret key objects | |
81 * Note: some attributes may also exist in one or two | |
82 * other object classes, but they are also listed | |
83 * because not all object have them. | |
84 */ | |
85 CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] = | |
86 { | |
87 CKA_VALUE_LEN, | |
88 CKA_ENCRYPT, | |
89 CKA_DECRYPT, | |
90 CKA_WRAP, | |
91 CKA_UNWRAP, | |
92 CKA_SIGN, | |
93 CKA_VERIFY, | |
94 CKA_SENSITIVE, | |
95 CKA_EXTRACTABLE, | |
96 CKA_NEVER_EXTRACTABLE, | |
97 CKA_ALWAYS_SENSITIVE | |
98 }; | |
99 | |
100 /* | |
101 * Validate the attribute by using binary search algorithm. | |
102 */ | |
103 CK_RV | |
104 kms_lookup_attr(CK_ATTRIBUTE_TYPE type) | |
105 { | |
106 size_t lower, middle, upper; | |
107 | |
108 lower = 0; | |
109 upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1; | |
110 | |
111 while (lower <= upper) { | |
112 /* Always starts from middle. */ | |
113 middle = (lower + upper) / 2; | |
114 | |
115 if (type > attr_map[middle]) { | |
116 /* Adjust the lower bound to upper half. */ | |
117 lower = middle + 1; | |
118 continue; | |
119 } | |
120 | |
121 if (type == attr_map[middle]) { | |
122 /* Found it. */ | |
123 return (CKR_OK); | |
124 } | |
125 | |
126 if (type < attr_map[middle]) { | |
127 /* Adjust the upper bound to lower half. */ | |
128 upper = middle - 1; | |
129 continue; | |
130 } | |
131 } | |
132 | |
133 /* Failed to find the matching attribute from the attribute table. */ | |
134 return (CKR_ATTRIBUTE_TYPE_INVALID); | |
135 } | |
136 | |
137 | |
138 /* | |
139 * Validate the attribute by using the following search algorithm: | |
140 * | |
141 * 1) Search for the most frequently used attributes first. | |
142 * 2) If not found, search for the usage-purpose attributes - these | |
143 * attributes have dense set of values, therefore compiler will | |
144 * optimize it with a branch table and branch to the appropriate | |
145 * case. | |
146 * 3) If still not found, use binary search for the rest of the | |
147 * attributes in the attr_map[] table. | |
148 */ | |
149 CK_RV | |
150 kms_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum, | |
151 CK_OBJECT_CLASS *class) | |
152 { | |
153 | |
154 CK_ULONG i; | |
155 CK_RV rv = CKR_OK; | |
156 | |
157 for (i = 0; i < ulAttrNum; i++) { | |
158 /* First tier search */ | |
159 switch (template[i].type) { | |
160 case CKA_CLASS: | |
161 *class = *((CK_OBJECT_CLASS*)template[i].pValue); | |
162 break; | |
163 case CKA_TOKEN: | |
164 break; | |
165 case CKA_KEY_TYPE: | |
166 break; | |
167 case CKA_VALUE: | |
168 break; | |
169 case CKA_VALUE_LEN: | |
170 break; | |
171 case CKA_VALUE_BITS: | |
172 break; | |
173 default: | |
174 /* Second tier search */ | |
175 switch (template[i].type) { | |
176 case CKA_ENCRYPT: | |
177 break; | |
178 case CKA_DECRYPT: | |
179 break; | |
180 case CKA_WRAP: | |
181 break; | |
182 case CKA_UNWRAP: | |
183 break; | |
184 case CKA_SIGN: | |
185 break; | |
186 case CKA_SIGN_RECOVER: | |
187 break; | |
188 case CKA_VERIFY: | |
189 break; | |
190 case CKA_VERIFY_RECOVER: | |
191 break; | |
192 case CKA_DERIVE: | |
193 break; | |
194 default: | |
195 /* Third tier search */ | |
196 rv = kms_lookup_attr(template[i].type); | |
197 if (rv != CKR_OK) | |
198 return (rv); | |
199 break; | |
200 } | |
201 break; | |
202 } | |
203 } | |
204 return (rv); | |
205 } | |
206 | |
207 | |
208 /* | |
209 * Clean up and release all the storage in the extra attribute list | |
210 * of an object. | |
211 */ | |
212 void | |
213 kms_cleanup_extra_attr(kms_object_t *object_p) | |
214 { | |
215 | |
216 CK_ATTRIBUTE_INFO_PTR extra_attr; | |
217 CK_ATTRIBUTE_INFO_PTR tmp; | |
218 | |
219 if (object_p == NULL) | |
220 return; | |
221 | |
222 extra_attr = object_p->extra_attrlistp; | |
223 while (extra_attr) { | |
224 tmp = extra_attr->next; | |
225 if (extra_attr->attr.pValue) | |
226 /* | |
227 * All extra attributes in the extra attribute | |
228 * list have pValue points to the value of the | |
229 * attribute (with simple byte array type). | |
230 * Free the storage for the value of the attribute. | |
231 */ | |
232 free(extra_attr->attr.pValue); | |
233 | |
234 /* Free the storage for the attribute_info struct. */ | |
235 free(extra_attr); | |
236 extra_attr = tmp; | |
237 } | |
238 | |
239 object_p->extra_attrlistp = NULL; | |
240 } | |
241 | |
242 /* | |
243 * Create the attribute_info struct to hold the object's attribute, | |
244 * and add it to the extra attribute list of an object. | |
245 */ | |
246 CK_RV | |
247 kms_add_extra_attr(CK_ATTRIBUTE_PTR template, kms_object_t *object_p) | |
248 { | |
249 | |
250 CK_ATTRIBUTE_INFO_PTR attrp; | |
251 | |
252 /* Allocate the storage for the attribute_info struct. */ | |
253 attrp = calloc(1, sizeof (attribute_info_t)); | |
254 if (attrp == NULL) { | |
255 return (CKR_HOST_MEMORY); | |
256 } | |
257 | |
258 /* Set up attribute_info struct. */ | |
259 attrp->attr.type = template->type; | |
260 attrp->attr.ulValueLen = template->ulValueLen; | |
261 | |
262 if ((template->pValue != NULL) && | |
263 (template->ulValueLen > 0)) { | |
264 /* Allocate storage for the value of the attribute. */ | |
265 attrp->attr.pValue = malloc(template->ulValueLen); | |
266 if (attrp->attr.pValue == NULL) { | |
267 free(attrp); | |
268 return (CKR_HOST_MEMORY); | |
269 } | |
270 | |
271 (void) memcpy(attrp->attr.pValue, template->pValue, | |
272 template->ulValueLen); | |
273 } else { | |
274 attrp->attr.pValue = NULL; | |
275 } | |
276 | |
277 /* Insert the new attribute in front of extra attribute list. */ | |
278 if (object_p->extra_attrlistp == NULL) { | |
279 object_p->extra_attrlistp = attrp; | |
280 attrp->next = NULL; | |
281 } else { | |
282 attrp->next = object_p->extra_attrlistp; | |
283 object_p->extra_attrlistp = attrp; | |
284 } | |
285 | |
286 return (CKR_OK); | |
287 } | |
288 | |
289 /* | |
290 * Copy the attribute_info struct from the old object to a new attribute_info | |
291 * struct, and add that new struct to the extra attribute list of the new | |
292 * object. | |
293 */ | |
294 CK_RV | |
295 kms_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, | |
296 kms_object_t *object_p) | |
297 { | |
298 CK_ATTRIBUTE_INFO_PTR attrp; | |
299 | |
300 /* Allocate attribute_info struct. */ | |
301 attrp = calloc(1, sizeof (attribute_info_t)); | |
302 if (attrp == NULL) { | |
303 return (CKR_HOST_MEMORY); | |
304 } | |
305 | |
306 attrp->attr.type = old_attrp->attr.type; | |
307 attrp->attr.ulValueLen = old_attrp->attr.ulValueLen; | |
308 | |
309 if ((old_attrp->attr.pValue != NULL) && | |
310 (old_attrp->attr.ulValueLen > 0)) { | |
311 attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen); | |
312 if (attrp->attr.pValue == NULL) { | |
313 free(attrp); | |
314 return (CKR_HOST_MEMORY); | |
315 } | |
316 | |
317 (void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue, | |
318 old_attrp->attr.ulValueLen); | |
319 } else { | |
320 attrp->attr.pValue = NULL; | |
321 } | |
322 | |
323 /* Insert the new attribute in front of extra attribute list */ | |
324 if (object_p->extra_attrlistp == NULL) { | |
325 object_p->extra_attrlistp = attrp; | |
326 attrp->next = NULL; | |
327 } else { | |
328 attrp->next = object_p->extra_attrlistp; | |
329 object_p->extra_attrlistp = attrp; | |
330 } | |
331 | |
332 return (CKR_OK); | |
333 } | |
334 | |
335 /* | |
336 * Get the attribute triple from the extra attribute list in the object | |
337 * (if the specified attribute type is found), and copy it to a template. | |
338 * Note the type of the attribute to be copied is specified by the template, | |
339 * and the storage is pre-allocated for the atrribute value in the template | |
340 * for doing the copy. | |
341 */ | |
342 CK_RV | |
343 get_extra_attr_from_object(kms_object_t *object_p, CK_ATTRIBUTE_PTR template) | |
344 { | |
345 CK_ATTRIBUTE_INFO_PTR extra_attr; | |
346 CK_ATTRIBUTE_TYPE type = template->type; | |
347 | |
348 extra_attr = object_p->extra_attrlistp; | |
349 | |
350 while (extra_attr) { | |
351 if (type == extra_attr->attr.type) { | |
352 /* Found it. */ | |
353 break; | |
354 } else { | |
355 /* Does not match, try next one. */ | |
356 extra_attr = extra_attr->next; | |
357 } | |
358 } | |
359 | |
360 if (extra_attr == NULL) { | |
361 /* A valid but un-initialized attribute. */ | |
362 template->ulValueLen = 0; | |
363 return (CKR_OK); | |
364 } | |
365 | |
366 /* | |
367 * We found the attribute in the extra attribute list. | |
368 */ | |
369 if (template->pValue == NULL) { | |
370 template->ulValueLen = extra_attr->attr.ulValueLen; | |
371 return (CKR_OK); | |
372 } | |
373 | |
374 if (template->ulValueLen >= extra_attr->attr.ulValueLen) { | |
375 /* | |
376 * The buffer provided by the application is large | |
377 * enough to hold the value of the attribute. | |
378 */ | |
379 (void) memcpy(template->pValue, extra_attr->attr.pValue, | |
380 extra_attr->attr.ulValueLen); | |
381 template->ulValueLen = extra_attr->attr.ulValueLen; | |
382 return (CKR_OK); | |
383 } else { | |
384 /* | |
385 * The buffer provided by the application does | |
386 * not have enough space to hold the value. | |
387 */ | |
388 template->ulValueLen = (CK_ULONG)-1; | |
389 return (CKR_BUFFER_TOO_SMALL); | |
390 } | |
391 } | |
392 | |
393 /* | |
394 * Modify the attribute triple in the extra attribute list of the object | |
395 * if the specified attribute type is found. Otherwise, just add it to | |
396 * list. | |
397 */ | |
398 CK_RV | |
399 set_extra_attr_to_object(kms_object_t *object_p, CK_ATTRIBUTE_TYPE type, | |
400 CK_ATTRIBUTE_PTR template) | |
401 { | |
402 CK_ATTRIBUTE_INFO_PTR extra_attr; | |
403 | |
404 extra_attr = object_p->extra_attrlistp; | |
405 | |
406 while (extra_attr) { | |
407 if (type == extra_attr->attr.type) { | |
408 /* Found it. */ | |
409 break; | |
410 } else { | |
411 /* Does not match, try next one. */ | |
412 extra_attr = extra_attr->next; | |
413 } | |
414 } | |
415 | |
416 if (extra_attr == NULL) { | |
417 /* | |
418 * This attribute is a new one, go ahead adding it to | |
419 * the extra attribute list. | |
420 */ | |
421 return (kms_add_extra_attr(template, object_p)); | |
422 } | |
423 | |
424 /* We found the attribute in the extra attribute list. */ | |
425 if ((template->pValue != NULL) && | |
426 (template->ulValueLen > 0)) { | |
427 if (template->ulValueLen > extra_attr->attr.ulValueLen) { | |
428 /* The old buffer is too small to hold the new value. */ | |
429 if (extra_attr->attr.pValue != NULL) | |
430 /* Free storage for the old attribute value. */ | |
431 free(extra_attr->attr.pValue); | |
432 | |
433 /* Allocate storage for the new attribute value. */ | |
434 extra_attr->attr.pValue = malloc(template->ulValueLen); | |
435 if (extra_attr->attr.pValue == NULL) { | |
436 return (CKR_HOST_MEMORY); | |
437 } | |
438 } | |
439 | |
440 /* Replace the attribute with new value. */ | |
441 extra_attr->attr.ulValueLen = template->ulValueLen; | |
442 (void) memcpy(extra_attr->attr.pValue, template->pValue, | |
443 template->ulValueLen); | |
444 } else { | |
445 extra_attr->attr.pValue = NULL; | |
446 } | |
447 | |
448 return (CKR_OK); | |
449 } | |
450 | |
451 /* | |
452 * Copy the boolean data type attribute value from an object for the | |
453 * specified attribute to the template. | |
454 */ | |
455 CK_RV | |
456 get_bool_attr_from_object(kms_object_t *object_p, CK_ULONG bool_flag, | |
457 CK_ATTRIBUTE_PTR template) | |
458 { | |
459 | |
460 if (template->pValue == NULL) { | |
461 template->ulValueLen = sizeof (CK_BBOOL); | |
462 return (CKR_OK); | |
463 } | |
464 | |
465 if (template->ulValueLen >= sizeof (CK_BBOOL)) { | |
466 /* | |
467 * The buffer provided by the application is large | |
468 * enough to hold the value of the attribute. | |
469 */ | |
470 if (object_p->bool_attr_mask & bool_flag) { | |
471 *((CK_BBOOL *)template->pValue) = B_TRUE; | |
472 } else { | |
473 *((CK_BBOOL *)template->pValue) = B_FALSE; | |
474 } | |
475 | |
476 template->ulValueLen = sizeof (CK_BBOOL); | |
477 return (CKR_OK); | |
478 } else { | |
479 /* | |
480 * The buffer provided by the application does | |
481 * not have enough space to hold the value. | |
482 */ | |
483 template->ulValueLen = (CK_ULONG)-1; | |
484 return (CKR_BUFFER_TOO_SMALL); | |
485 } | |
486 } | |
487 | |
488 /* | |
489 * Set the boolean data type attribute value in the object. | |
490 */ | |
491 CK_RV | |
492 set_bool_attr_to_object(kms_object_t *object_p, CK_ULONG bool_flag, | |
493 CK_ATTRIBUTE_PTR template) | |
494 { | |
495 | |
496 if (*(CK_BBOOL *)template->pValue) | |
497 object_p->bool_attr_mask |= bool_flag; | |
498 else | |
499 object_p->bool_attr_mask &= ~bool_flag; | |
500 | |
501 return (CKR_OK); | |
502 } | |
503 | |
504 | |
505 /* | |
506 * Copy the CK_ULONG data type attribute value from an object to the | |
507 * template. | |
508 */ | |
509 CK_RV | |
510 get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template) | |
511 { | |
512 | |
513 if (template->pValue == NULL) { | |
514 template->ulValueLen = sizeof (CK_ULONG); | |
515 return (CKR_OK); | |
516 } | |
517 | |
518 if (template->ulValueLen >= sizeof (CK_ULONG)) { | |
519 /* | |
520 * The buffer provided by the application is large | |
521 * enough to hold the value of the attribute. | |
522 */ | |
523 *(CK_ULONG_PTR)template->pValue = value; | |
524 template->ulValueLen = sizeof (CK_ULONG); | |
525 return (CKR_OK); | |
526 } else { | |
527 /* | |
528 * The buffer provided by the application does | |
529 * not have enough space to hold the value. | |
530 */ | |
531 template->ulValueLen = (CK_ULONG)-1; | |
532 return (CKR_BUFFER_TOO_SMALL); | |
533 } | |
534 } | |
535 | |
536 CK_RV | |
537 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src) | |
538 { | |
539 if ((src->pValue != NULL) && | |
540 (src->ulValueLen > 0)) { | |
541 /* Allocate storage for the value of the attribute. */ | |
542 dest->pValue = malloc(src->ulValueLen); | |
543 if (dest->pValue == NULL) { | |
544 return (CKR_HOST_MEMORY); | |
545 } | |
546 | |
547 (void) memcpy(dest->pValue, src->pValue, | |
548 src->ulValueLen); | |
549 dest->ulValueLen = src->ulValueLen; | |
550 dest->type = src->type; | |
551 } else { | |
552 dest->pValue = NULL; | |
553 dest->ulValueLen = 0; | |
554 dest->type = src->type; | |
555 } | |
556 | |
557 return (CKR_OK); | |
558 | |
559 } | |
560 | |
561 void | |
562 string_attr_cleanup(CK_ATTRIBUTE_PTR template) | |
563 { | |
564 | |
565 if (template->pValue) { | |
566 free(template->pValue); | |
567 template->pValue = NULL; | |
568 template->ulValueLen = 0; | |
569 } | |
570 } | |
571 | |
572 /* | |
573 * Parse the common attributes. Return to caller with appropriate return | |
574 * value to indicate if the supplied template specifies a valid attribute | |
575 * with a valid value. | |
576 */ | |
577 static CK_RV | |
578 kms_parse_common_attrs(CK_ATTRIBUTE_PTR template, uint64_t *attr_mask_p) | |
579 { | |
580 CK_RV rv = CKR_OK; | |
581 kms_slot_t *pslot = get_slotinfo(); | |
582 | |
583 switch (template->type) { | |
584 case CKA_CLASS: | |
585 break; | |
586 case CKA_TOKEN: | |
587 if ((*(CK_BBOOL *)template->pValue) == TRUE) | |
588 *attr_mask_p |= TOKEN_BOOL_ON; | |
589 break; | |
590 | |
591 case CKA_PRIVATE: | |
592 if ((*(CK_BBOOL *)template->pValue) == TRUE) { | |
593 /* | |
594 * Cannot create a private object if the token | |
595 * has a keystore and the user isn't logged in. | |
596 */ | |
597 if (pslot->sl_state != CKU_USER) { | |
598 rv = CKR_ATTRIBUTE_VALUE_INVALID; | |
599 } else { | |
600 *attr_mask_p |= PRIVATE_BOOL_ON; | |
601 } | |
602 } | |
603 break; | |
604 | |
605 case CKA_MODIFIABLE: | |
606 if ((*(CK_BBOOL *)template->pValue) == FALSE) { | |
607 *attr_mask_p &= ~MODIFIABLE_BOOL_ON; | |
608 } | |
609 break; | |
610 | |
611 case CKA_LABEL: | |
612 break; | |
613 | |
614 default: | |
615 rv = CKR_TEMPLATE_INCONSISTENT; | |
616 } | |
617 | |
618 return (rv); | |
619 } | |
620 | |
621 /* | |
622 * Build a Secret Key Object. | |
623 * | |
624 * - Parse the object's template, and when an error is detected such as | |
625 * invalid attribute type, invalid attribute value, etc., return | |
626 * with appropriate return value. | |
627 * - Set up attribute mask field in the object for the supplied common | |
628 * attributes that have boolean type. | |
629 * - Build the attribute_info struct to hold the value of each supplied | |
630 * attribute that has byte array type. Link attribute_info structs | |
631 * together to form the extra attribute list of the object. | |
632 * - Allocate storage for the Secret Key object. | |
633 * - Build the Secret Key object. Allocate storage to hold the big integer | |
634 * value for the attribute CKA_VALUE that is required for all the key | |
635 * types supported by secret key object. | |
636 * | |
637 */ | |
638 CK_RV | |
639 kms_build_secret_key_object(CK_ATTRIBUTE_PTR template, | |
640 CK_ULONG ulAttrNum, kms_object_t *new_object) | |
641 { | |
642 int i; | |
643 CK_KEY_TYPE keytype = (CK_KEY_TYPE)~0UL; | |
644 uint64_t attr_mask; | |
645 CK_RV rv = CKR_OK; | |
646 int isLabel = 0; | |
647 /* Must not set flags */ | |
648 int isValueLen = 0; | |
649 CK_ATTRIBUTE string_tmp; | |
650 secret_key_obj_t *sck; | |
651 | |
652 string_tmp.pValue = NULL; | |
653 | |
654 /* | |
655 * If the object was pulled from the KMS, the | |
656 * attributes are encoded in the object record | |
657 * before this function is called, we don't | |
658 * want to overwrite them unless the attribute | |
659 * template says differently. | |
660 */ | |
661 if (new_object->bool_attr_mask != 0) | |
662 attr_mask = new_object->bool_attr_mask; | |
663 else | |
664 attr_mask = SECRET_KEY_DEFAULT; | |
665 | |
666 /* Allocate storage for Secret Key Object. */ | |
667 sck = calloc(1, sizeof (secret_key_obj_t)); | |
668 if (sck == NULL) { | |
669 rv = CKR_HOST_MEMORY; | |
670 goto fail_cleanup; | |
671 } | |
672 | |
673 new_object->object_class_u.secret_key = sck; | |
674 new_object->class = CKO_SECRET_KEY; | |
675 | |
676 for (i = 0; i < ulAttrNum; i++) { | |
677 | |
678 /* Secret Key Object Attributes */ | |
679 switch (template[i].type) { | |
680 | |
681 /* common key attributes */ | |
682 case CKA_KEY_TYPE: | |
683 keytype = *((CK_KEY_TYPE*)template[i].pValue); | |
684 break; | |
685 | |
686 case CKA_ID: | |
687 case CKA_START_DATE: | |
688 case CKA_END_DATE: | |
689 /* | |
690 * Allocate storage to hold the attribute | |
691 * value with byte array type, and add it to | |
692 * the extra attribute list of the object. | |
693 */ | |
694 rv = kms_add_extra_attr(&template[i], | |
695 new_object); | |
696 if (rv != CKR_OK) { | |
697 goto fail_cleanup; | |
698 } | |
699 break; | |
700 | |
701 /* | |
702 * The following key related attribute types must | |
703 * not be specified by C_CreateObject. | |
704 */ | |
705 case CKA_LOCAL: | |
706 case CKA_KEY_GEN_MECHANISM: | |
707 case CKA_ALWAYS_SENSITIVE: | |
708 case CKA_NEVER_EXTRACTABLE: | |
709 rv = CKR_TEMPLATE_INCONSISTENT; | |
710 goto fail_cleanup; | |
711 | |
712 /* Key related boolean attributes */ | |
713 case CKA_DERIVE: | |
714 if (*(CK_BBOOL *)template[i].pValue) | |
715 attr_mask |= DERIVE_BOOL_ON; | |
716 break; | |
717 | |
718 case CKA_SENSITIVE: | |
719 if (*(CK_BBOOL *)template[i].pValue) | |
720 attr_mask |= SENSITIVE_BOOL_ON; | |
721 break; | |
722 | |
723 case CKA_ENCRYPT: | |
724 if (*(CK_BBOOL *)template[i].pValue) | |
725 attr_mask |= ENCRYPT_BOOL_ON; | |
726 else | |
727 attr_mask &= ~ENCRYPT_BOOL_ON; | |
728 break; | |
729 | |
730 case CKA_DECRYPT: | |
731 if (*(CK_BBOOL *)template[i].pValue) | |
732 attr_mask |= DECRYPT_BOOL_ON; | |
733 else | |
734 attr_mask &= ~DECRYPT_BOOL_ON; | |
735 break; | |
736 | |
737 case CKA_SIGN: | |
738 if (*(CK_BBOOL *)template[i].pValue) | |
739 attr_mask |= SIGN_BOOL_ON; | |
740 else | |
741 attr_mask &= ~SIGN_BOOL_ON; | |
742 break; | |
743 | |
744 case CKA_VERIFY: | |
745 if (*(CK_BBOOL *)template[i].pValue) | |
746 attr_mask |= VERIFY_BOOL_ON; | |
747 else | |
748 attr_mask &= ~VERIFY_BOOL_ON; | |
749 break; | |
750 | |
751 case CKA_WRAP: | |
752 if (*(CK_BBOOL *)template[i].pValue) | |
753 attr_mask |= WRAP_BOOL_ON; | |
754 break; | |
755 | |
756 case CKA_UNWRAP: | |
757 if (*(CK_BBOOL *)template[i].pValue) | |
758 attr_mask |= UNWRAP_BOOL_ON; | |
759 break; | |
760 | |
761 case CKA_EXTRACTABLE: | |
762 if (*(CK_BBOOL *)template[i].pValue) | |
763 attr_mask |= EXTRACTABLE_BOOL_ON; | |
764 else | |
765 attr_mask &= ~EXTRACTABLE_BOOL_ON; | |
766 break; | |
767 | |
768 case CKA_VALUE: | |
769 if ((template[i].ulValueLen == 0) || | |
770 (template[i].pValue == NULL)) { | |
771 rv = CKR_ATTRIBUTE_VALUE_INVALID; | |
772 goto fail_cleanup; | |
773 } | |
774 /* | |
775 * Copyin attribute from template | |
776 * to a local variable. | |
777 */ | |
778 sck->sk_value = malloc(template[i].ulValueLen); | |
779 if (sck->sk_value == NULL) { | |
780 rv = CKR_HOST_MEMORY; | |
781 goto fail_cleanup; | |
782 } | |
783 (void) memcpy(sck->sk_value, template[i].pValue, | |
784 template[i].ulValueLen); | |
785 sck->sk_value_len = template[i].ulValueLen; | |
786 break; | |
787 | |
788 case CKA_VALUE_LEN: | |
789 isValueLen = 1; | |
790 if (template[i].pValue != NULL) | |
791 sck->sk_value_len = | |
792 *(CK_ULONG_PTR)template[i].pValue; | |
793 else | |
794 sck->sk_value_len = 0; | |
795 break; | |
796 | |
797 case CKA_LABEL: | |
798 isLabel = 1; | |
799 rv = get_string_from_template(&string_tmp, | |
800 &template[i]); | |
801 if (rv != CKR_OK) | |
802 goto fail_cleanup; | |
803 break; | |
804 | |
805 default: | |
806 rv = kms_parse_common_attrs(&template[i], &attr_mask); | |
807 if (rv != CKR_OK) | |
808 goto fail_cleanup; | |
809 break; | |
810 | |
811 } | |
812 } /* For */ | |
813 | |
814 if (keytype == (CK_KEY_TYPE)~0UL) { | |
815 rv = CKR_TEMPLATE_INCOMPLETE; | |
816 goto fail_cleanup; | |
817 } | |
818 | |
819 new_object->key_type = keytype; | |
820 | |
821 /* Supported key types of the Secret Key Object */ | |
822 switch (keytype) { | |
823 | |
824 case CKK_AES: | |
825 if (!isValueLen) { | |
826 rv = CKR_TEMPLATE_INCOMPLETE; | |
827 goto fail_cleanup; | |
828 } | |
829 if (sck->sk_value_len != AES_MIN_KEY_BYTES && | |
830 sck->sk_value_len != AES_192_KEY_BYTES && | |
831 sck->sk_value_len != AES_MAX_KEY_BYTES) { | |
832 rv = CKR_ATTRIBUTE_VALUE_INVALID; | |
833 goto fail_cleanup; | |
834 } | |
835 break; | |
836 | |
837 case CKK_RC4: | |
838 case CKK_GENERIC_SECRET: | |
839 case CKK_BLOWFISH: | |
840 case CKK_DES: | |
841 case CKK_DES2: | |
842 case CKK_DES3: | |
843 default: | |
844 rv = CKR_TEMPLATE_INCONSISTENT; | |
845 goto fail_cleanup; | |
846 } | |
847 | |
848 /* Set up object. */ | |
849 new_object->bool_attr_mask = attr_mask; | |
850 if (isLabel) { | |
851 rv = kms_add_extra_attr(&string_tmp, new_object); | |
852 if (rv != CKR_OK) | |
853 goto fail_cleanup; | |
854 string_attr_cleanup(&string_tmp); | |
855 } | |
856 | |
857 return (rv); | |
858 | |
859 fail_cleanup: | |
860 /* | |
861 * cleanup the storage allocated to the local variables. | |
862 */ | |
863 string_attr_cleanup(&string_tmp); | |
864 | |
865 /* | |
866 * cleanup the storage allocated inside the object itself. | |
867 */ | |
868 kms_cleanup_object(new_object); | |
869 | |
870 return (rv); | |
871 } | |
872 | |
873 /* | |
874 * Validate the attribute types in the object's template. Then, | |
875 * call the appropriate build function according to the class of | |
876 * the object specified in the template. | |
877 * | |
878 * Note: The following classes of objects are supported: | |
879 * - CKO_SECRET_KEY | |
880 */ | |
881 CK_RV | |
882 kms_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum, | |
883 kms_object_t *new_object) | |
884 { | |
885 CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL; | |
886 CK_RV rv = CKR_OK; | |
887 | |
888 if (template == NULL) { | |
889 return (CKR_ARGUMENTS_BAD); | |
890 } | |
891 | |
892 /* Validate the attribute type in the template. */ | |
893 rv = kms_validate_attr(template, ulAttrNum, &class); | |
894 if (rv != CKR_OK) | |
895 return (rv); | |
896 | |
897 if (class == (CK_OBJECT_CLASS)~0UL) | |
898 return (CKR_TEMPLATE_INCOMPLETE); | |
899 | |
900 /* | |
901 * Call the appropriate function based on the supported class | |
902 * of the object. | |
903 */ | |
904 switch (class) { | |
905 | |
906 case CKO_SECRET_KEY: | |
907 rv = kms_build_secret_key_object(template, ulAttrNum, | |
908 new_object); | |
909 break; | |
910 | |
911 case CKO_DOMAIN_PARAMETERS: | |
912 case CKO_DATA: | |
913 case CKO_CERTIFICATE: | |
914 case CKO_HW_FEATURE: | |
915 case CKO_VENDOR_DEFINED: | |
916 case CKO_PUBLIC_KEY: | |
917 case CKO_PRIVATE_KEY: | |
918 default: | |
919 return (CKR_ATTRIBUTE_VALUE_INVALID); | |
920 } | |
921 | |
922 return (rv); | |
923 } | |
924 | |
925 | |
926 /* | |
927 * Get the value of a requested attribute that is common to all supported | |
928 * classes (i.e. public key, private key, secret key classes). | |
929 */ | |
930 CK_RV | |
931 kms_get_common_attrs(kms_object_t *object_p, CK_ATTRIBUTE_PTR template) | |
932 { | |
933 | |
934 CK_RV rv = CKR_OK; | |
935 | |
936 switch (template->type) { | |
937 | |
938 case CKA_CLASS: | |
939 return (get_ulong_attr_from_object(object_p->class, | |
940 template)); | |
941 | |
942 /* default boolean attributes */ | |
943 case CKA_TOKEN: | |
944 template->ulValueLen = sizeof (CK_BBOOL); | |
945 if (template->pValue == NULL) { | |
946 return (CKR_OK); | |
947 } | |
948 | |
949 *((CK_BBOOL *)template->pValue) = B_FALSE; | |
950 break; | |
951 | |
952 case CKA_PRIVATE: | |
953 | |
954 template->ulValueLen = sizeof (CK_BBOOL); | |
955 if (template->pValue == NULL) { | |
956 return (CKR_OK); | |
957 } | |
958 if (object_p->bool_attr_mask & PRIVATE_BOOL_ON) { | |
959 *((CK_BBOOL *)template->pValue) = B_TRUE; | |
960 } else { | |
961 *((CK_BBOOL *)template->pValue) = B_FALSE; | |
962 } | |
963 break; | |
964 | |
965 case CKA_MODIFIABLE: | |
966 template->ulValueLen = sizeof (CK_BBOOL); | |
967 if (template->pValue == NULL) { | |
968 return (CKR_OK); | |
969 } | |
970 if ((object_p->bool_attr_mask) & MODIFIABLE_BOOL_ON) | |
971 *((CK_BBOOL *)template->pValue) = B_TRUE; | |
972 else | |
973 *((CK_BBOOL *)template->pValue) = B_FALSE; | |
974 break; | |
975 | |
976 case CKA_LABEL: | |
977 return (get_extra_attr_from_object(object_p, | |
978 template)); | |
979 break; | |
980 | |
981 default: | |
982 /* | |
983 * The specified attribute for the object is invalid. | |
984 * (the object does not possess such an attribute.) | |
985 */ | |
986 template->ulValueLen = (CK_ULONG)-1; | |
987 return (CKR_ATTRIBUTE_TYPE_INVALID); | |
988 } | |
989 | |
990 return (rv); | |
991 } | |
992 | |
993 /* | |
994 * Get the value of a requested attribute that is common to all key objects | |
995 * (i.e. public key, private key and secret key). | |
996 */ | |
997 CK_RV | |
998 kms_get_common_key_attrs(kms_object_t *object_p, | |
999 CK_ATTRIBUTE_PTR template) | |
1000 { | |
1001 | |
1002 switch (template->type) { | |
1003 | |
1004 case CKA_KEY_TYPE: | |
1005 return (get_ulong_attr_from_object(object_p->key_type, | |
1006 template)); | |
1007 | |
1008 case CKA_ID: | |
1009 case CKA_START_DATE: | |
1010 case CKA_END_DATE: | |
1011 /* | |
1012 * The above extra attributes have byte array type. | |
1013 */ | |
1014 return (get_extra_attr_from_object(object_p, | |
1015 template)); | |
1016 | |
1017 /* Key related boolean attributes */ | |
1018 case CKA_LOCAL: | |
1019 return (get_bool_attr_from_object(object_p, | |
1020 LOCAL_BOOL_ON, template)); | |
1021 | |
1022 case CKA_DERIVE: | |
1023 return (get_bool_attr_from_object(object_p, | |
1024 DERIVE_BOOL_ON, template)); | |
1025 | |
1026 case CKA_KEY_GEN_MECHANISM: | |
1027 return (get_ulong_attr_from_object(object_p->mechanism, | |
1028 template)); | |
1029 | |
1030 default: | |
1031 return (CKR_ATTRIBUTE_TYPE_INVALID); | |
1032 } | |
1033 } | |
1034 | |
1035 /* | |
1036 * Get the value of a requested attribute of a Secret Key Object. | |
1037 * | |
1038 * Rule: All the attributes in the secret key object can be revealed | |
1039 * except those marked with footnote number "7" when the object | |
1040 * has its CKA_SENSITIVE attribute set to TRUE or its | |
1041 * CKA_EXTRACTABLE attribute set to FALSE. | |
1042 */ | |
1043 CK_RV | |
1044 kms_get_secret_key_attribute(kms_object_t *object_p, | |
1045 CK_ATTRIBUTE_PTR template) | |
1046 { | |
1047 | |
1048 CK_RV rv = CKR_OK; | |
1049 CK_KEY_TYPE keytype = object_p->key_type; | |
1050 | |
1051 switch (template->type) { | |
1052 | |
1053 /* Key related boolean attributes */ | |
1054 case CKA_SENSITIVE: | |
1055 return (get_bool_attr_from_object(object_p, | |
1056 SENSITIVE_BOOL_ON, template)); | |
1057 | |
1058 case CKA_ENCRYPT: | |
1059 return (get_bool_attr_from_object(object_p, | |
1060 ENCRYPT_BOOL_ON, template)); | |
1061 | |
1062 case CKA_DECRYPT: | |
1063 return (get_bool_attr_from_object(object_p, | |
1064 DECRYPT_BOOL_ON, template)); | |
1065 | |
1066 case CKA_SIGN: | |
1067 return (get_bool_attr_from_object(object_p, | |
1068 SIGN_BOOL_ON, template)); | |
1069 | |
1070 case CKA_VERIFY: | |
1071 return (get_bool_attr_from_object(object_p, | |
1072 VERIFY_BOOL_ON, template)); | |
1073 | |
1074 case CKA_WRAP: | |
1075 return (get_bool_attr_from_object(object_p, | |
1076 WRAP_BOOL_ON, template)); | |
1077 | |
1078 case CKA_UNWRAP: | |
1079 return (get_bool_attr_from_object(object_p, | |
1080 UNWRAP_BOOL_ON, template)); | |
1081 | |
1082 case CKA_EXTRACTABLE: | |
1083 return (get_bool_attr_from_object(object_p, | |
1084 EXTRACTABLE_BOOL_ON, template)); | |
1085 | |
1086 case CKA_ALWAYS_SENSITIVE: | |
1087 return (get_bool_attr_from_object(object_p, | |
1088 ALWAYS_SENSITIVE_BOOL_ON, template)); | |
1089 | |
1090 case CKA_NEVER_EXTRACTABLE: | |
1091 return (get_bool_attr_from_object(object_p, | |
1092 NEVER_EXTRACTABLE_BOOL_ON, template)); | |
1093 | |
1094 case CKA_VALUE: | |
1095 /* | |
1096 * If the specified attribute for the secret key object | |
1097 * cannot be revealed because the object is sensitive | |
1098 * or unextractable, then the ulValueLen is set to -1. | |
1099 */ | |
1100 if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) || | |
1101 !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) { | |
1102 template->ulValueLen = (CK_ULONG)-1; | |
1103 return (CKR_ATTRIBUTE_SENSITIVE); | |
1104 } | |
1105 | |
1106 switch (keytype) { | |
1107 case CKK_AES: | |
1108 /* | |
1109 * Copy secret key object attributes to template. | |
1110 */ | |
1111 if (template->pValue == NULL) { | |
1112 template->ulValueLen = | |
1113 OBJ_SEC_VALUE_LEN(object_p); | |
1114 return (CKR_OK); | |
1115 } | |
1116 | |
1117 if (OBJ_SEC_VALUE(object_p) == NULL) { | |
1118 template->ulValueLen = 0; | |
1119 return (CKR_OK); | |
1120 } | |
1121 | |
1122 if (template->ulValueLen >= | |
1123 OBJ_SEC_VALUE_LEN(object_p)) { | |
1124 (void) memcpy(template->pValue, | |
1125 OBJ_SEC_VALUE(object_p), | |
1126 OBJ_SEC_VALUE_LEN(object_p)); | |
1127 template->ulValueLen = | |
1128 OBJ_SEC_VALUE_LEN(object_p); | |
1129 return (CKR_OK); | |
1130 } else { | |
1131 template->ulValueLen = (CK_ULONG)-1; | |
1132 return (CKR_BUFFER_TOO_SMALL); | |
1133 } | |
1134 | |
1135 case CKK_RC4: | |
1136 case CKK_GENERIC_SECRET: | |
1137 case CKK_RC5: | |
1138 case CKK_DES: | |
1139 case CKK_DES2: | |
1140 case CKK_DES3: | |
1141 case CKK_CDMF: | |
1142 case CKK_BLOWFISH: | |
1143 default: | |
1144 template->ulValueLen = (CK_ULONG)-1; | |
1145 rv = CKR_ATTRIBUTE_TYPE_INVALID; | |
1146 break; | |
1147 } | |
1148 break; | |
1149 | |
1150 case CKA_VALUE_LEN: | |
1151 return (get_ulong_attr_from_object(OBJ_SEC_VALUE_LEN(object_p), | |
1152 template)); | |
1153 | |
1154 default: | |
1155 /* | |
1156 * First, get the value of the request attribute defined | |
1157 * in the list of common key attributes. If the request | |
1158 * attribute is not found in that list, then get the | |
1159 * attribute from the list of common attributes. | |
1160 */ | |
1161 rv = kms_get_common_key_attrs(object_p, template); | |
1162 if (rv == CKR_ATTRIBUTE_TYPE_INVALID) { | |
1163 rv = kms_get_common_attrs(object_p, template); | |
1164 } | |
1165 break; | |
1166 } | |
1167 | |
1168 return (rv); | |
1169 | |
1170 } | |
1171 | |
1172 /* | |
1173 * Call the appropriate get attribute function according to the class | |
1174 * of object. | |
1175 * | |
1176 * The caller of this function holds the lock on the object. | |
1177 */ | |
1178 CK_RV | |
1179 kms_get_attribute(kms_object_t *object_p, CK_ATTRIBUTE_PTR template) | |
1180 { | |
1181 | |
1182 CK_RV rv = CKR_OK; | |
1183 CK_OBJECT_CLASS class = object_p->class; | |
1184 | |
1185 switch (class) { | |
1186 case CKO_SECRET_KEY: | |
1187 rv = kms_get_secret_key_attribute(object_p, template); | |
1188 break; | |
1189 | |
1190 case CKO_PRIVATE_KEY: | |
1191 case CKO_PUBLIC_KEY: | |
1192 default: | |
1193 /* | |
1194 * If the specified attribute for the object is invalid | |
1195 * (the object does not possess such as attribute), then | |
1196 * the ulValueLen is modified to hold the value -1. | |
1197 */ | |
1198 template->ulValueLen = (CK_ULONG)-1; | |
1199 return (CKR_ATTRIBUTE_TYPE_INVALID); | |
1200 } | |
1201 | |
1202 return (rv); | |
1203 | |
1204 } | |
1205 | |
1206 /* | |
1207 * Set the value of an attribute that is common to all key objects | |
1208 * (i.e. public key, private key and secret key). | |
1209 */ | |
1210 static CK_RV | |
1211 kms_set_common_key_attribute(kms_object_t *object_p, | |
1212 CK_ATTRIBUTE_PTR template, boolean_t copy) | |
1213 { | |
1214 | |
1215 kms_slot_t *pslot = get_slotinfo(); | |
1216 CK_RV rv = CKR_OK; | |
1217 | |
1218 switch (template->type) { | |
1219 | |
1220 case CKA_LABEL: | |
1221 /* | |
1222 * Only the LABEL can be modified in the common storage | |
1223 * object attributes after the object is created. | |
1224 */ | |
1225 return (set_extra_attr_to_object(object_p, | |
1226 CKA_LABEL, template)); | |
1227 | |
1228 case CKA_ID: | |
1229 return (set_extra_attr_to_object(object_p, | |
1230 CKA_ID, template)); | |
1231 | |
1232 case CKA_START_DATE: | |
1233 return (set_extra_attr_to_object(object_p, | |
1234 CKA_START_DATE, template)); | |
1235 | |
1236 case CKA_END_DATE: | |
1237 return (set_extra_attr_to_object(object_p, | |
1238 CKA_END_DATE, template)); | |
1239 | |
1240 case CKA_DERIVE: | |
1241 return (set_bool_attr_to_object(object_p, | |
1242 DERIVE_BOOL_ON, template)); | |
1243 | |
1244 case CKA_CLASS: | |
1245 case CKA_KEY_TYPE: | |
1246 case CKA_LOCAL: | |
1247 return (CKR_ATTRIBUTE_READ_ONLY); | |
1248 | |
1249 case CKA_PRIVATE: | |
1250 if (!copy) { | |
1251 /* called from C_SetAttributeValue() */ | |
1252 return (CKR_ATTRIBUTE_READ_ONLY); | |
1253 } | |
1254 | |
1255 /* called from C_CopyObject() */ | |
1256 if ((*(CK_BBOOL *)template->pValue) != B_TRUE) { | |
1257 return (CKR_OK); | |
1258 } | |
1259 | |
1260 (void) pthread_mutex_lock(&pslot->sl_mutex); | |
1261 /* | |
1262 * Cannot create a private object if the token | |
1263 * has a keystore and the user isn't logged in. | |
1264 */ | |
1265 if (pslot->sl_state != CKU_USER) { | |
1266 rv = CKR_USER_NOT_LOGGED_IN; | |
1267 } else { | |
1268 rv = set_bool_attr_to_object(object_p, | |
1269 PRIVATE_BOOL_ON, template); | |
1270 } | |
1271 (void) pthread_mutex_unlock(&pslot->sl_mutex); | |
1272 return (rv); | |
1273 | |
1274 case CKA_MODIFIABLE: | |
1275 if (copy) { | |
1276 rv = set_bool_attr_to_object(object_p, | |
1277 MODIFIABLE_BOOL_ON, template); | |
1278 } else { | |
1279 rv = CKR_ATTRIBUTE_READ_ONLY; | |
1280 } | |
1281 return (rv); | |
1282 | |
1283 default: | |
1284 return (CKR_TEMPLATE_INCONSISTENT); | |
1285 } | |
1286 | |
1287 } | |
1288 | |
1289 /* | |
1290 * Set the value of an attribute of a Secret Key Object. | |
1291 * | |
1292 * Rule: The attributes marked with footnote number "8" in the PKCS11 | |
1293 * spec may be modified (p.88 in PKCS11 spec.). | |
1294 */ | |
1295 static CK_RV | |
1296 kms_set_secret_key_attribute(kms_object_t *object_p, | |
1297 CK_ATTRIBUTE_PTR template, boolean_t copy) | |
1298 { | |
1299 CK_KEY_TYPE keytype = object_p->key_type; | |
1300 | |
1301 switch (template->type) { | |
1302 | |
1303 case CKA_SENSITIVE: | |
1304 /* | |
1305 * Cannot set SENSITIVE to FALSE if it is already ON. | |
1306 */ | |
1307 if (((*(CK_BBOOL *)template->pValue) == B_FALSE) && | |
1308 (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) { | |
1309 return (CKR_ATTRIBUTE_READ_ONLY); | |
1310 } | |
1311 | |
1312 if (*(CK_BBOOL *)template->pValue) | |
1313 object_p->bool_attr_mask |= SENSITIVE_BOOL_ON; | |
1314 return (CKR_OK); | |
1315 | |
1316 case CKA_ENCRYPT: | |
1317 return (set_bool_attr_to_object(object_p, | |
1318 ENCRYPT_BOOL_ON, template)); | |
1319 | |
1320 case CKA_DECRYPT: | |
1321 return (set_bool_attr_to_object(object_p, | |
1322 DECRYPT_BOOL_ON, template)); | |
1323 | |
1324 case CKA_SIGN: | |
1325 return (set_bool_attr_to_object(object_p, | |
1326 SIGN_BOOL_ON, template)); | |
1327 | |
1328 case CKA_VERIFY: | |
1329 return (set_bool_attr_to_object(object_p, | |
1330 VERIFY_BOOL_ON, template)); | |
1331 | |
1332 case CKA_WRAP: | |
1333 return (set_bool_attr_to_object(object_p, | |
1334 WRAP_BOOL_ON, template)); | |
1335 | |
1336 case CKA_UNWRAP: | |
1337 return (set_bool_attr_to_object(object_p, | |
1338 UNWRAP_BOOL_ON, template)); | |
1339 | |
1340 case CKA_EXTRACTABLE: | |
1341 /* | |
1342 * Cannot set EXTRACTABLE to TRUE if it is already OFF. | |
1343 */ | |
1344 if ((*(CK_BBOOL *)template->pValue) && | |
1345 !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) { | |
1346 return (CKR_ATTRIBUTE_READ_ONLY); | |
1347 } | |
1348 | |
1349 if ((*(CK_BBOOL *)template->pValue) == B_FALSE) | |
1350 object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON; | |
1351 return (CKR_OK); | |
1352 | |
1353 case CKA_VALUE: | |
1354 return (CKR_ATTRIBUTE_READ_ONLY); | |
1355 | |
1356 case CKA_VALUE_LEN: | |
1357 if ((keytype == CKK_RC4) || | |
1358 (keytype == CKK_GENERIC_SECRET) || | |
1359 (keytype == CKK_AES) || | |
1360 (keytype == CKK_BLOWFISH)) | |
1361 return (CKR_ATTRIBUTE_READ_ONLY); | |
1362 break; | |
1363 | |
1364 default: | |
1365 /* | |
1366 * Set the value of a common key attribute. | |
1367 */ | |
1368 return (kms_set_common_key_attribute(object_p, | |
1369 template, copy)); | |
1370 } | |
1371 | |
1372 /* | |
1373 * If we got this far, then the combination of key type | |
1374 * and requested attribute is invalid. | |
1375 */ | |
1376 return (CKR_ATTRIBUTE_TYPE_INVALID); | |
1377 } | |
1378 | |
1379 /* | |
1380 * Call the appropriate set attribute function according to the class | |
1381 * of object. | |
1382 * | |
1383 * The caller of this function does not hold the lock on the original | |
1384 * object, since this function is setting the attribute on the new object | |
1385 * that is being modified. | |
1386 * | |
1387 */ | |
1388 CK_RV | |
1389 kms_set_attribute(kms_object_t *object_p, CK_ATTRIBUTE_PTR template, | |
1390 boolean_t copy) | |
1391 { | |
1392 | |
1393 CK_RV rv = CKR_OK; | |
1394 CK_OBJECT_CLASS class = object_p->class; | |
1395 | |
1396 switch (class) { | |
1397 | |
1398 case CKO_SECRET_KEY: | |
1399 rv = kms_set_secret_key_attribute(object_p, template, | |
1400 copy); | |
1401 break; | |
1402 | |
1403 case CKO_PUBLIC_KEY: | |
1404 case CKO_PRIVATE_KEY: | |
1405 default: | |
1406 /* | |
1407 * If the template specifies a value of an attribute | |
1408 * which is incompatible with other existing attributes | |
1409 * of the object, then fails with return code | |
1410 * CKR_TEMPLATE_INCONSISTENT. | |
1411 */ | |
1412 rv = CKR_TEMPLATE_INCONSISTENT; | |
1413 break; | |
1414 } | |
1415 | |
1416 return (rv); | |
1417 } | |
1418 | |
1419 CK_RV | |
1420 kms_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p, | |
1421 secret_key_obj_t **new_secret_key_obj_p) | |
1422 { | |
1423 secret_key_obj_t *sk; | |
1424 | |
1425 sk = malloc(sizeof (secret_key_obj_t)); | |
1426 if (sk == NULL) { | |
1427 return (CKR_HOST_MEMORY); | |
1428 } | |
1429 (void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t)); | |
1430 | |
1431 /* copy the secret key value */ | |
1432 sk->sk_value = malloc((sizeof (CK_BYTE) * sk->sk_value_len)); | |
1433 if (sk->sk_value == NULL) { | |
1434 free(sk); | |
1435 return (CKR_HOST_MEMORY); | |
1436 } | |
1437 (void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value, | |
1438 (sizeof (CK_BYTE) * sk->sk_value_len)); | |
1439 | |
1440 *new_secret_key_obj_p = sk; | |
1441 | |
1442 return (CKR_OK); | |
1443 } | |
1444 | |
1445 | |
1446 | |
1447 /* | |
1448 * If CKA_CLASS not given, guess CKA_CLASS using | |
1449 * attributes on template. | |
1450 * | |
1451 * Some attributes are specific to an object class. If one or more | |
1452 * of these attributes are in the template, make a list of classes | |
1453 * that can have these attributes. This would speed up the search later, | |
1454 * because we can immediately skip an object if the class of that | |
1455 * object can not possibly contain one of the attributes. | |
1456 * | |
1457 */ | |
1458 void | |
1459 kms_process_find_attr(CK_OBJECT_CLASS *pclasses, | |
1460 CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate, | |
1461 CK_ULONG ulCount) | |
1462 { | |
1463 ulong_t i; | |
1464 int j; | |
1465 boolean_t secret_found = B_FALSE; | |
1466 int num_secret_key_attrs; | |
1467 int num_pclasses = 0; | |
1468 | |
1469 for (i = 0; i < ulCount; i++) { | |
1470 if (pTemplate[i].type == CKA_CLASS) { | |
1471 /* | |
1472 * don't need to guess the class, it is specified. | |
1473 * Just record the class, and return. | |
1474 */ | |
1475 pclasses[0] = | |
1476 (*((CK_OBJECT_CLASS *)pTemplate[i].pValue)); | |
1477 *num_result_pclasses = 1; | |
1478 return; | |
1479 } | |
1480 } | |
1481 | |
1482 num_secret_key_attrs = | |
1483 sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE); | |
1484 | |
1485 /* | |
1486 * Get the list of objects class that might contain | |
1487 * some attributes. | |
1488 */ | |
1489 for (i = 0; i < ulCount; i++) { | |
1490 if (!secret_found) { | |
1491 for (j = 0; j < num_secret_key_attrs; j++) { | |
1492 if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) { | |
1493 secret_found = B_TRUE; | |
1494 pclasses[num_pclasses++] = | |
1495 CKO_SECRET_KEY; | |
1496 break; | |
1497 } | |
1498 } | |
1499 } | |
1500 } | |
1501 *num_result_pclasses = num_pclasses; | |
1502 } | |
1503 | |
1504 | |
1505 boolean_t | |
1506 kms_find_match_attrs(kms_object_t *obj, CK_OBJECT_CLASS *pclasses, | |
1507 CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr) | |
1508 { | |
1509 ulong_t i; | |
1510 CK_ATTRIBUTE *tmpl_attr, *obj_attr; | |
1511 uint64_t attr_mask; | |
1512 boolean_t compare_attr, compare_boolean; | |
1513 | |
1514 /* | |
1515 * Check if the class of this object match with any | |
1516 * of object classes that can possibly contain the | |
1517 * requested attributes. | |
1518 */ | |
1519 if (num_pclasses > 0) { | |
1520 for (i = 0; i < num_pclasses; i++) { | |
1521 if (obj->class == pclasses[i]) { | |
1522 break; | |
1523 } | |
1524 } | |
1525 if (i == num_pclasses) { | |
1526 /* | |
1527 * this object can't possibly contain one or | |
1528 * more attributes, don't need to check this object | |
1529 */ | |
1530 return (B_FALSE); | |
1531 } | |
1532 } | |
1533 | |
1534 /* need to examine everything */ | |
1535 for (i = 0; i < num_attr; i++) { | |
1536 tmpl_attr = &(template[i]); | |
1537 compare_attr = B_FALSE; | |
1538 compare_boolean = B_FALSE; | |
1539 switch (tmpl_attr->type) { | |
1540 /* First, check the most common attributes */ | |
1541 case CKA_CLASS: | |
1542 if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) != | |
1543 obj->class) { | |
1544 return (B_FALSE); | |
1545 } | |
1546 break; | |
1547 case CKA_KEY_TYPE: | |
1548 if (*((CK_KEY_TYPE *)tmpl_attr->pValue) != | |
1549 obj->key_type) { | |
1550 return (B_FALSE); | |
1551 } | |
1552 break; | |
1553 case CKA_ENCRYPT: | |
1554 attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON; | |
1555 compare_boolean = B_TRUE; | |
1556 break; | |
1557 case CKA_DECRYPT: | |
1558 attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON; | |
1559 compare_boolean = B_TRUE; | |
1560 break; | |
1561 case CKA_WRAP: | |
1562 attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON; | |
1563 compare_boolean = B_TRUE; | |
1564 break; | |
1565 case CKA_UNWRAP: | |
1566 attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON; | |
1567 compare_boolean = B_TRUE; | |
1568 break; | |
1569 case CKA_SIGN: | |
1570 attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON; | |
1571 compare_boolean = B_TRUE; | |
1572 break; | |
1573 case CKA_SIGN_RECOVER: | |
1574 attr_mask = (obj->bool_attr_mask) & | |
1575 SIGN_RECOVER_BOOL_ON; | |
1576 compare_boolean = B_TRUE; | |
1577 break; | |
1578 case CKA_VERIFY: | |
1579 attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON; | |
1580 compare_boolean = B_TRUE; | |
1581 break; | |
1582 case CKA_VERIFY_RECOVER: | |
1583 attr_mask = (obj->bool_attr_mask) & | |
1584 VERIFY_RECOVER_BOOL_ON; | |
1585 compare_boolean = B_TRUE; | |
1586 break; | |
1587 case CKA_DERIVE: | |
1588 attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON; | |
1589 compare_boolean = B_TRUE; | |
1590 break; | |
1591 case CKA_LOCAL: | |
1592 attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON; | |
1593 compare_boolean = B_TRUE; | |
1594 break; | |
1595 case CKA_SENSITIVE: | |
1596 attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON; | |
1597 compare_boolean = B_TRUE; | |
1598 break; | |
1599 case CKA_SECONDARY_AUTH: | |
1600 attr_mask = (obj->bool_attr_mask) & | |
1601 SECONDARY_AUTH_BOOL_ON; | |
1602 compare_boolean = B_TRUE; | |
1603 break; | |
1604 case CKA_TRUSTED: | |
1605 attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON; | |
1606 compare_boolean = B_TRUE; | |
1607 break; | |
1608 case CKA_EXTRACTABLE: | |
1609 attr_mask = (obj->bool_attr_mask) & | |
1610 EXTRACTABLE_BOOL_ON; | |
1611 compare_boolean = B_TRUE; | |
1612 break; | |
1613 case CKA_ALWAYS_SENSITIVE: | |
1614 attr_mask = (obj->bool_attr_mask) & | |
1615 ALWAYS_SENSITIVE_BOOL_ON; | |
1616 compare_boolean = B_TRUE; | |
1617 break; | |
1618 case CKA_NEVER_EXTRACTABLE: | |
1619 attr_mask = (obj->bool_attr_mask) & | |
1620 NEVER_EXTRACTABLE_BOOL_ON; | |
1621 compare_boolean = B_TRUE; | |
1622 break; | |
1623 case CKA_TOKEN: | |
1624 attr_mask = (obj->bool_attr_mask) & TOKEN_BOOL_ON; | |
1625 compare_boolean = B_TRUE; | |
1626 break; | |
1627 case CKA_PRIVATE: | |
1628 attr_mask = (obj->bool_attr_mask) & PRIVATE_BOOL_ON; | |
1629 compare_boolean = B_TRUE; | |
1630 break; | |
1631 case CKA_MODIFIABLE: | |
1632 attr_mask = (obj->bool_attr_mask) & MODIFIABLE_BOOL_ON; | |
1633 compare_boolean = B_TRUE; | |
1634 break; | |
1635 case CKA_SUBJECT: | |
1636 case CKA_ID: | |
1637 case CKA_START_DATE: | |
1638 case CKA_END_DATE: | |
1639 case CKA_KEY_GEN_MECHANISM: | |
1640 case CKA_LABEL: | |
1641 /* find these attributes from extra_attrlistp */ | |
1642 obj_attr = get_extra_attr(tmpl_attr->type, obj); | |
1643 compare_attr = B_TRUE; | |
1644 break; | |
1645 case CKA_VALUE_LEN: | |
1646 /* only secret key has this attribute */ | |
1647 if (obj->class == CKO_SECRET_KEY) { | |
1648 if (*((CK_ULONG *)tmpl_attr->pValue) != | |
1649 OBJ_SEC_VALUE_LEN(obj)) { | |
1650 return (B_FALSE); | |
1651 } | |
1652 } else { | |
1653 return (B_FALSE); | |
1654 } | |
1655 break; | |
1656 case CKA_VALUE: | |
1657 switch (obj->class) { | |
1658 case CKO_SECRET_KEY: | |
1659 break; | |
1660 default: | |
1661 return (B_FALSE); | |
1662 } | |
1663 break; | |
1664 case CKA_VALUE_BITS: | |
1665 case CKA_PRIME_BITS: | |
1666 case CKA_SUBPRIME_BITS: | |
1667 default: | |
1668 /* | |
1669 * any other attributes are currently not supported. | |
1670 * so, it's not possible for them to be in the | |
1671 * object | |
1672 */ | |
1673 return (B_FALSE); | |
1674 } | |
1675 if (compare_boolean) { | |
1676 CK_BBOOL bval; | |
1677 | |
1678 if (attr_mask) { | |
1679 bval = TRUE; | |
1680 } else { | |
1681 bval = FALSE; | |
1682 } | |
1683 if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) { | |
1684 return (B_FALSE); | |
1685 } | |
1686 } else if (compare_attr) { | |
1687 if (obj_attr == NULL) { | |
1688 /* | |
1689 * The attribute type is valid, and its value | |
1690 * has not been initialized in the object. In | |
1691 * this case, it only matches the template's | |
1692 * attribute if the template's value length | |
1693 * is 0. | |
1694 */ | |
1695 if (tmpl_attr->ulValueLen != 0) | |
1696 return (B_FALSE); | |
1697 } else { | |
1698 if (tmpl_attr->ulValueLen != | |
1699 obj_attr->ulValueLen) { | |
1700 return (B_FALSE); | |
1701 } | |
1702 if (memcmp(tmpl_attr->pValue, obj_attr->pValue, | |
1703 tmpl_attr->ulValueLen) != 0) { | |
1704 return (B_FALSE); | |
1705 } | |
1706 } | |
1707 } | |
1708 } | |
1709 return (B_TRUE); | |
1710 } | |
1711 | |
1712 CK_ATTRIBUTE_PTR | |
1713 get_extra_attr(CK_ATTRIBUTE_TYPE type, kms_object_t *obj) | |
1714 { | |
1715 CK_ATTRIBUTE_INFO_PTR tmp; | |
1716 | |
1717 tmp = obj->extra_attrlistp; | |
1718 while (tmp != NULL) { | |
1719 if (tmp->attr.type == type) { | |
1720 return (&(tmp->attr)); | |
1721 } | |
1722 tmp = tmp->next; | |
1723 } | |
1724 /* if get there, the specified attribute is not found */ | |
1725 return (NULL); | |
1726 } |