1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <strings.h>
27 #include <errno.h>
28 #include <ecc_impl.h>
29 #include <security/cryptoki.h>
30 #include <sys/crypto/ioctl.h>
31 #include "kernelGlobal.h"
32 #include "kernelSession.h"
33 #include "kernelObject.h"
34
35 static boolean_t
attribute_in_template(CK_ATTRIBUTE_TYPE type,CK_ATTRIBUTE_PTR t,CK_ULONG cnt)36 attribute_in_template(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
37 {
38 int i;
39
40 for (i = 0; i < cnt; i++) {
41 if (t[i].type == type)
42 return (B_TRUE);
43 }
44 return (B_FALSE);
45 }
46
47 /*
48 * This routine returns modulus bytes rounded up to the nearest 8 byte
49 * chunk. This is so we don't have to pass in max sized buffers for
50 * returned attributes. Every unnecessary byte that we pass in results
51 * in a kernel allocation.
52 */
53 static ulong_t
get_modulus_bytes(CK_ATTRIBUTE_PTR t,CK_ULONG cnt)54 get_modulus_bytes(CK_ATTRIBUTE_PTR t, CK_ULONG cnt)
55 {
56 CK_ULONG modulus_len;
57 int i;
58
59 for (i = 0; i < cnt; i++) {
60 if (t[i].type == CKA_MODULUS_BITS) {
61 get_ulong_attr_from_template(&modulus_len, &t[i]);
62 /* convert from bit length to byte length */
63 modulus_len = (modulus_len - 1) / 64 + 1;
64 return (modulus_len * 8);
65 }
66 }
67 return (0);
68 }
69
70 /*
71 * Remove specified attribute from array. Storage for the attribute's
72 * value is freed if 'free_attr' is TRUE. Attributes are shifted so they are
73 * contiguous within the array, i.e. the next attribute is shifted into
74 * the position of the removed attribute. Returns TRUE if specified
75 * attribute is removed.
76 */
77 static boolean_t
remove_one_attribute(CK_ATTRIBUTE_PTR t,CK_ULONG type,uint_t count,boolean_t free_attr)78 remove_one_attribute(CK_ATTRIBUTE_PTR t, CK_ULONG type, uint_t count,
79 boolean_t free_attr)
80 {
81 int i, j;
82
83 for (i = 0, j = 0; i < count; i++) {
84 if (t[i].type == type) {
85 if (free_attr) {
86 free(t[i].pValue);
87 }
88 continue;
89 }
90 if (i != j) {
91 t[j].type = t[i].type;
92 t[j].pValue = t[i].pValue;
93 t[j].ulValueLen = t[i].ulValueLen;
94 }
95 j++;
96 }
97 if (j == count)
98 return (B_FALSE);
99
100 /* safety */
101 t[j].pValue = NULL;
102 t[j].ulValueLen = 0;
103 return (B_TRUE);
104 }
105
106 static boolean_t
is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount)107 is_secret_key_template(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount)
108 {
109 int i;
110 for (i = 0; i < ulAttributeCount; i++) {
111 if (pTemplate[i].type == CKA_CLASS &&
112 *(CK_OBJECT_CLASS *)(pTemplate[i].pValue) ==
113 CKO_SECRET_KEY)
114 return (B_TRUE);
115 }
116 return (B_FALSE);
117 }
118
119 /*
120 * Allocate a template with space for new_count entries and copy the
121 * specified template into the new template.
122 */
123 static CK_ATTRIBUTE_PTR
grow_template(CK_ATTRIBUTE_PTR old_template,CK_ULONG old_count,CK_ULONG new_count)124 grow_template(CK_ATTRIBUTE_PTR old_template, CK_ULONG old_count,
125 CK_ULONG new_count)
126 {
127 CK_ATTRIBUTE_PTR new_template;
128
129 new_template = malloc(new_count * sizeof (CK_ATTRIBUTE));
130 if (new_template != NULL)
131 bcopy(old_template, new_template,
132 old_count * sizeof (CK_ATTRIBUTE));
133 return (new_template);
134 }
135
136 /*
137 * For fixed length keys such as DES, return the length based on
138 * the key type. For variable length keys such as AES, take the
139 * length from the CKA_VALUE_LEN attribute.
140 */
141 static int
get_key_len_from_template(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_object_t * basekey_p,ulong_t * key_len)142 get_key_len_from_template(CK_MECHANISM_PTR pMechanism,
143 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
144 kernel_object_t *basekey_p, ulong_t *key_len)
145 {
146 boolean_t fixed_len_key = B_FALSE;
147 ulong_t key_type;
148 int i;
149
150 for (i = 0; i < ulAttributeCount; i++) {
151 if (pTemplate[i].type == CKA_KEY_TYPE) {
152 get_ulong_attr_from_template(&key_type, &pTemplate[i]);
153 break;
154 }
155 }
156 /* CKA_KEY_TYPE must be present */
157 if (i == ulAttributeCount)
158 return (CKR_TEMPLATE_INCOMPLETE);
159
160 switch (key_type) {
161 case CKK_DES:
162 *key_len = 8;
163 fixed_len_key = B_TRUE;
164 break;
165 case CKK_DES3:
166 *key_len = 24;
167 fixed_len_key = B_TRUE;
168 break;
169 case CKK_AES:
170 case CKK_BLOWFISH:
171 for (i = 0; i < ulAttributeCount; i++) {
172 if (pTemplate[i].type == CKA_VALUE_LEN) {
173 get_ulong_attr_from_template(key_len,
174 &pTemplate[i]);
175 break;
176 }
177 }
178 /* CKA_VALUE_LEN must be present */
179 if (i == ulAttributeCount)
180 return (CKR_TEMPLATE_INCOMPLETE);
181 break;
182 case CKK_GENERIC_SECRET:
183 /*
184 * The key will not be truncated, so we need to
185 * get the max length for the mechanism.
186 */
187 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE) {
188 CK_ATTRIBUTE tmp;
189
190 tmp.type = CKA_PRIME;
191 tmp.pValue = NULL;
192
193 /* get size of attribute */
194 if (kernel_get_attribute(basekey_p, &tmp) != CKR_OK) {
195 return (CKR_ARGUMENTS_BAD);
196 }
197 *key_len = tmp.ulValueLen;
198 } else if (pMechanism->mechanism == CKM_ECDH1_DERIVE) {
199 *key_len = EC_MAX_VALUE_LEN;
200 } else {
201 return (CKR_ARGUMENTS_BAD);
202 }
203 break;
204 default:
205 return (CKR_ATTRIBUTE_VALUE_INVALID);
206 }
207
208 if (fixed_len_key && attribute_in_template(CKA_VALUE_LEN,
209 pTemplate, ulAttributeCount))
210 return (CKR_TEMPLATE_INCONSISTENT);
211
212 return (CKR_OK);
213 }
214
215 /* find specified attribute src template and copy to dest */
216 static int
copy_attribute(CK_ULONG type,CK_ATTRIBUTE_PTR src,CK_ULONG src_cnt,CK_ATTRIBUTE_PTR dst)217 copy_attribute(CK_ULONG type, CK_ATTRIBUTE_PTR src, CK_ULONG src_cnt,
218 CK_ATTRIBUTE_PTR dst)
219 {
220 int rv, i;
221
222 for (i = 0; i < src_cnt; i++) {
223 if (src[i].type == type) {
224 rv = get_string_from_template(dst, &src[i]);
225 break;
226 }
227 }
228 /*
229 * The public template didn't have attribute.
230 */
231 if (i == src_cnt) {
232 rv = CKR_TEMPLATE_INCOMPLETE;
233 }
234 return (rv);
235 }
236
237 static void
free_attributes(caddr_t p,uint_t * countp)238 free_attributes(caddr_t p, uint_t *countp)
239 {
240 if (*countp > 0) {
241 free_object_attributes(p, *countp);
242 *countp = 0;
243 }
244 }
245
246 CK_RV
key_gen_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_objp)247 key_gen_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
248 CK_ULONG ulCount, kernel_session_t *session_p,
249 crypto_mech_type_t k_mech_type, kernel_object_t *new_objp)
250 {
251 crypto_nostore_generate_key_t obj_ngk;
252 char *key_buf = NULL;
253 CK_ATTRIBUTE_PTR newTemplate = NULL;
254 CK_BBOOL is_token_obj = FALSE;
255 CK_RV rv = CKR_OK;
256 ulong_t key_len = 0;
257 uint_t attr_count;
258 int r;
259
260 obj_ngk.ngk_in_count = 0;
261 obj_ngk.ngk_out_count = 0;
262
263 rv = get_key_len_from_template(pMechanism, pTemplate, ulCount,
264 NULL, &key_len);
265 if (rv != CRYPTO_SUCCESS)
266 goto failed_exit;
267
268 if ((key_buf = malloc(key_len)) == NULL) {
269 rv = CKR_HOST_MEMORY;
270 goto failed_exit;
271 }
272
273 attr_count = ulCount + 1;
274 newTemplate = grow_template(pTemplate, ulCount, attr_count);
275 if (newTemplate == NULL) {
276 rv = CKR_HOST_MEMORY;
277 goto failed_exit;
278 }
279
280 /* Now add the CKA_VALUE attribute to template */
281 newTemplate[ulCount].type = CKA_VALUE;
282 newTemplate[ulCount].pValue = (caddr_t)key_buf;
283 newTemplate[ulCount].ulValueLen = key_len;
284
285 rv = process_object_attributes(newTemplate, attr_count - 1,
286 &obj_ngk.ngk_in_attributes, &is_token_obj);
287 if (rv != CKR_OK) {
288 goto failed_exit;
289 }
290 rv = process_object_attributes(&newTemplate[ulCount],
291 1, &obj_ngk.ngk_out_attributes, &is_token_obj);
292 if (rv != CKR_OK) {
293 goto failed_exit;
294 }
295
296 /* Cannot create a token object with a READ-ONLY session. */
297 if (is_token_obj && session_p->ses_RO) {
298 rv = CKR_SESSION_READ_ONLY;
299 goto failed_exit;
300 }
301
302 /* Call the CRYPTO_NOSTORE_GENERATE_KEY ioctl */
303 obj_ngk.ngk_session = session_p->k_session;
304 obj_ngk.ngk_in_count = attr_count - 1;
305 obj_ngk.ngk_out_count = 1;
306 obj_ngk.ngk_mechanism.cm_type = k_mech_type;
307 obj_ngk.ngk_mechanism.cm_param = pMechanism->pParameter;
308 obj_ngk.ngk_mechanism.cm_param_len = pMechanism->ulParameterLen;
309
310 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY,
311 &obj_ngk)) < 0) {
312 if (errno != EINTR)
313 break;
314 }
315 if (r < 0) {
316 rv = CKR_FUNCTION_FAILED;
317 } else {
318 rv = crypto2pkcs11_error_number(obj_ngk.ngk_return_value);
319 }
320 free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
321 if (rv != CKR_OK) {
322 goto failed_exit;
323 }
324
325 rv = get_object_attributes(&newTemplate[ulCount], 1,
326 obj_ngk.ngk_out_attributes);
327 free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
328 if (rv != CRYPTO_SUCCESS) {
329 goto failed_exit;
330 }
331
332 /*
333 * CKA_VALUE_LEN is not stored with the secret key object,
334 * so we remove it by shifting attributes down one.
335 */
336 (void) remove_one_attribute(newTemplate, CKA_VALUE_LEN,
337 attr_count, B_FALSE);
338
339 rv = kernel_build_object(newTemplate, attr_count - 1,
340 new_objp, session_p, KERNEL_GEN_KEY);
341 if (rv != CRYPTO_SUCCESS) {
342 goto failed_exit;
343 }
344 new_objp->is_lib_obj = B_TRUE;
345 new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
346 (void) free(newTemplate);
347 bzero(key_buf, key_len);
348 (void) free(key_buf);
349 return (CKR_OK);
350
351 failed_exit:
352 free_attributes(obj_ngk.ngk_in_attributes, &obj_ngk.ngk_in_count);
353 free_attributes(obj_ngk.ngk_out_attributes, &obj_ngk.ngk_out_count);
354 if (key_buf != NULL) {
355 bzero(key_buf, key_len);
356 (void) free(key_buf);
357 }
358 if (newTemplate != NULL) {
359 (void) free(newTemplate);
360 }
361 return (rv);
362 }
363
364 CK_RV
C_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)365 C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
366 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
367 {
368 CK_RV rv = CKR_OK;
369 kernel_session_t *session_p;
370 kernel_object_t *new_objp = NULL;
371 kernel_slot_t *pslot;
372 boolean_t ses_lock_held = B_FALSE;
373 CK_BBOOL is_pri_obj;
374 CK_BBOOL is_token_obj = FALSE;
375 crypto_mech_type_t k_mech_type;
376 int r;
377
378 if (!kernel_initialized)
379 return (CKR_CRYPTOKI_NOT_INITIALIZED);
380
381 /* Obtain the session pointer */
382 rv = handle2session(hSession, &session_p);
383 if (rv != CKR_OK)
384 return (rv);
385
386 if ((pMechanism == NULL) || (phKey == NULL)) {
387 rv = CKR_ARGUMENTS_BAD;
388 goto failed_exit;
389 }
390
391 if ((pTemplate == NULL) && (ulCount != 0)) {
392 rv = CKR_ARGUMENTS_BAD;
393 goto failed_exit;
394 }
395
396 /* Get the kernel's internal mechanism number. */
397 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
398 if (rv != CKR_OK) {
399 goto failed_exit;
400 }
401
402 /* Create an object wrapper in the library first */
403 new_objp = calloc(1, sizeof (kernel_object_t));
404 if (new_objp == NULL) {
405 rv = CKR_HOST_MEMORY;
406 goto failed_exit;
407 }
408
409 /*
410 * Special Case: if token does not support object creation,
411 * but does support key generation by value, then create a session
412 * object and initialize with value returned by token.
413 */
414 pslot = slot_table[session_p->ses_slotid];
415 if (!pslot->sl_func_list.fl_object_create) {
416 rv = key_gen_by_value(pMechanism, pTemplate, ulCount, session_p,
417 k_mech_type, new_objp);
418 if (rv != CKR_OK)
419 goto failed_exit;
420 } else {
421 crypto_object_generate_key_t obj_gk;
422
423 /* Process the attributes */
424 rv = process_object_attributes(pTemplate, ulCount,
425 &obj_gk.gk_attributes, &is_token_obj);
426 if (rv != CKR_OK) {
427 goto failed_exit;
428 }
429 /* Cannot create a token object with a READ-ONLY session. */
430 if (is_token_obj && session_p->ses_RO) {
431 free_object_attributes(obj_gk.gk_attributes, ulCount);
432 rv = CKR_SESSION_READ_ONLY;
433 goto failed_exit;
434 }
435
436 /* Call the CRYPTO_GENERATE_KEY ioctl */
437 obj_gk.gk_session = session_p->k_session;
438 obj_gk.gk_count = ulCount;
439 obj_gk.gk_mechanism.cm_type = k_mech_type;
440 obj_gk.gk_mechanism.cm_param = pMechanism->pParameter;
441 obj_gk.gk_mechanism.cm_param_len = pMechanism->ulParameterLen;
442
443 while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY,
444 &obj_gk)) < 0) {
445 if (errno != EINTR)
446 break;
447 }
448 if (r < 0) {
449 rv = CKR_FUNCTION_FAILED;
450 } else {
451 rv = crypto2pkcs11_error_number(obj_gk.gk_return_value);
452 }
453
454 free_object_attributes(obj_gk.gk_attributes, ulCount);
455
456 if (rv != CKR_OK) {
457 goto failed_exit;
458 }
459
460 /* Get the value of the CKA_PRIVATE attribute. */
461 rv = get_cka_private_value(session_p, obj_gk.gk_handle,
462 &is_pri_obj);
463 if (rv != CKR_OK) {
464 goto failed_exit;
465 }
466
467 /*
468 * Store the kernel object handle in the object wrapper and
469 * initialize the library object.
470 */
471 new_objp->k_handle = obj_gk.gk_handle;
472 new_objp->is_lib_obj = B_FALSE;
473 new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
474 new_objp->extra_attrlistp = NULL;
475
476 if (is_pri_obj)
477 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
478 else
479 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
480
481 if (is_token_obj)
482 new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
483 else
484 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
485 }
486
487 (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
488 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
489
490 /*
491 * Add the new object to the slot's token object list if it is a
492 * a token object. Otherwise, add it to the session's object list.
493 */
494 if (is_token_obj) {
495 pslot = slot_table[session_p->ses_slotid];
496 kernel_add_token_object_to_slot(new_objp, pslot);
497 } else {
498 kernel_add_object_to_session(new_objp, session_p);
499 }
500
501 *phKey = (CK_OBJECT_HANDLE)new_objp;
502 REFRELE(session_p, ses_lock_held);
503 return (rv);
504
505 failed_exit:
506 if (new_objp != NULL) {
507 (void) free(new_objp);
508 }
509
510 REFRELE(session_p, ses_lock_held);
511 return (rv);
512 }
513
514 CK_RV
key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)515 key_gen_rsa_by_value(CK_MECHANISM_PTR pMechanism,
516 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
517 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
518 kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
519 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
520 {
521 crypto_nostore_generate_key_pair_t obj_nkp;
522 CK_ATTRIBUTE_PTR pubTemplate = NULL;
523 CK_ATTRIBUTE_PTR priTemplate = NULL;
524 CK_RV rv = CKR_OK;
525 CK_BBOOL is_token_obj1 = FALSE;
526 CK_BBOOL is_token_obj2 = FALSE;
527 uint_t pub_attr_count, pri_attr_count;
528 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
529 char public_modulus[512];
530 char public_exponent[8];
531 char private_exponent[512];
532 char private_modulus[512];
533 char prime_1[512];
534 char prime_2[512];
535 char exponent_1[512];
536 char exponent_2[512];
537 char coefficient[512];
538 CK_ULONG pub_class = CKO_PUBLIC_KEY;
539 CK_ULONG pri_class = CKO_PRIVATE_KEY;
540 CK_ULONG key_type;
541 CK_ULONG modulus_bytes;
542 boolean_t has_class, has_key_type, has_pub_exponent;
543 int n, r;
544
545 obj_nkp.nkp_in_public_count = 0;
546 obj_nkp.nkp_out_public_count = 0;
547 obj_nkp.nkp_in_private_count = 0;
548 obj_nkp.nkp_out_private_count = 0;
549
550 /* modulus bits must be present when generating a RSA key pair */
551 if (!attribute_in_template(CKA_MODULUS_BITS, pPublicKeyTemplate,
552 ulPublicKeyAttributeCount)) {
553 rv = CKR_TEMPLATE_INCOMPLETE;
554 goto failed_exit;
555 }
556
557 modulus_bytes = get_modulus_bytes(pPublicKeyTemplate,
558 ulPublicKeyAttributeCount);
559
560 /*
561 * Add CKA_MODULUS to the public template.
562 * This attribute must not be in the template.
563 */
564 if (attribute_in_template(CKA_MODULUS, pPublicKeyTemplate,
565 ulPublicKeyAttributeCount)) {
566 rv = CKR_TEMPLATE_INCONSISTENT;
567 goto failed_exit;
568 }
569 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
570 ulPublicKeyAttributeCount);
571 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
572 ulPublicKeyAttributeCount);
573 has_pub_exponent = attribute_in_template(CKA_PUBLIC_EXPONENT,
574 pPublicKeyTemplate, ulPublicKeyAttributeCount);
575
576 pub_attr_count = ulPublicKeyAttributeCount + 1;
577 if (!has_class)
578 pub_attr_count++;
579 if (!has_key_type)
580 pub_attr_count++;
581 if (!has_pub_exponent)
582 pub_attr_count++;
583 pubTemplate = grow_template(pPublicKeyTemplate,
584 ulPublicKeyAttributeCount, pub_attr_count);
585 if (pubTemplate == NULL) {
586 rv = CKR_HOST_MEMORY;
587 goto failed_exit;
588 }
589
590 n = ulPublicKeyAttributeCount;
591 if (!has_class) {
592 pubTemplate[n].type = CKA_CLASS;
593 pubTemplate[n].pValue = (caddr_t)&pub_class;
594 pubTemplate[n].ulValueLen = sizeof (pub_class);
595 n++;
596 }
597 if (!has_key_type) {
598 pubTemplate[n].type = CKA_KEY_TYPE;
599 key_type = CKK_RSA;
600 pubTemplate[n].pValue = (caddr_t)&key_type;
601 pubTemplate[n].ulValueLen = sizeof (key_type);
602 n++;
603 }
604 if (!has_pub_exponent) {
605 pubTemplate[n].type = CKA_PUBLIC_EXPONENT;
606 pubTemplate[n].pValue = (caddr_t)public_exponent;
607 pubTemplate[n].ulValueLen = modulus_bytes;
608 n++;
609 pub_out_attr_count++;
610 }
611 pubTemplate[n].type = CKA_MODULUS;
612 pubTemplate[n].pValue = (caddr_t)public_modulus;
613 pubTemplate[n].ulValueLen = modulus_bytes;
614 pub_out_attr_count++;
615
616 rv = process_object_attributes(pubTemplate,
617 pub_attr_count - pub_out_attr_count,
618 &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
619 if (rv != CKR_OK) {
620 goto failed_exit;
621 }
622 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
623
624 rv = process_object_attributes(
625 &pubTemplate[pub_attr_count - pub_out_attr_count],
626 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
627 &is_token_obj1);
628 if (rv != CKR_OK) {
629 goto failed_exit;
630 }
631 obj_nkp.nkp_out_public_count = pub_out_attr_count;
632
633 /*
634 * Cannot create a token object with a READ-ONLY
635 * session.
636 */
637 if (is_token_obj1 && session_p->ses_RO) {
638 rv = CKR_SESSION_READ_ONLY;
639 goto failed_exit;
640 }
641
642 /*
643 * Add CKA_MODULUS and CKA_PRIVATE_EXPONENT
644 * to the private template. These attributes
645 * must not be in the template.
646 */
647 if (attribute_in_template(CKA_PRIVATE_EXPONENT,
648 pPrivateKeyTemplate, ulPrivateKeyAttributeCount) ||
649 attribute_in_template(CKA_MODULUS,
650 pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) {
651 rv = CKR_TEMPLATE_INCONSISTENT;
652 goto failed_exit;
653 }
654 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
655 ulPrivateKeyAttributeCount);
656 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
657 ulPrivateKeyAttributeCount);
658
659 pri_attr_count = ulPrivateKeyAttributeCount + 7;
660 if (!has_class)
661 pri_attr_count++;
662 if (!has_key_type)
663 pri_attr_count++;
664
665 /* allocate space for CKA_PUBLIC_EXPONENT */
666 priTemplate = grow_template(pPrivateKeyTemplate,
667 ulPrivateKeyAttributeCount, pri_attr_count + 1);
668 if (priTemplate == NULL) {
669 rv = CKR_HOST_MEMORY;
670 goto failed_exit;
671 }
672 n = ulPrivateKeyAttributeCount;
673 if (!has_class) {
674 priTemplate[n].type = CKA_CLASS;
675 priTemplate[n].pValue = (caddr_t)&pri_class;
676 priTemplate[n].ulValueLen = sizeof (pri_class);
677 n++;
678 }
679 if (!has_key_type) {
680 priTemplate[n].type = CKA_KEY_TYPE;
681 key_type = CKK_RSA;
682 priTemplate[n].pValue = (caddr_t)&key_type;
683 priTemplate[n].ulValueLen = sizeof (key_type);
684 n++;
685 }
686 priTemplate[n].type = CKA_MODULUS;
687 priTemplate[n].pValue = (caddr_t)private_modulus;
688 priTemplate[n].ulValueLen = modulus_bytes;
689 pri_out_attr_count++;
690
691 n++;
692 priTemplate[n].type = CKA_PRIVATE_EXPONENT;
693 priTemplate[n].pValue = (caddr_t)private_exponent;
694 priTemplate[n].ulValueLen = modulus_bytes;
695 pri_out_attr_count++;
696
697 n++;
698 priTemplate[n].type = CKA_PRIME_1;
699 priTemplate[n].pValue = (caddr_t)prime_1;
700 priTemplate[n].ulValueLen = modulus_bytes/2;
701 pri_out_attr_count++;
702
703 n++;
704 priTemplate[n].type = CKA_PRIME_2;
705 priTemplate[n].pValue = (caddr_t)prime_2;
706 priTemplate[n].ulValueLen = modulus_bytes/2;
707 pri_out_attr_count++;
708
709 n++;
710 priTemplate[n].type = CKA_EXPONENT_1;
711 priTemplate[n].pValue = (caddr_t)exponent_1;
712 priTemplate[n].ulValueLen = modulus_bytes/2;
713 pri_out_attr_count++;
714
715 n++;
716 priTemplate[n].type = CKA_EXPONENT_2;
717 priTemplate[n].pValue = (caddr_t)exponent_2;
718 priTemplate[n].ulValueLen = modulus_bytes/2;
719 pri_out_attr_count++;
720
721 n++;
722 priTemplate[n].type = CKA_COEFFICIENT;
723 priTemplate[n].pValue = (caddr_t)coefficient;
724 priTemplate[n].ulValueLen = modulus_bytes/2;
725 pri_out_attr_count++;
726
727 rv = process_object_attributes(priTemplate,
728 pri_attr_count - pri_out_attr_count,
729 &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
730 if (rv != CKR_OK) {
731 goto failed_exit;
732 }
733 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
734
735 rv = process_object_attributes(
736 &priTemplate[pri_attr_count - pri_out_attr_count],
737 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
738 &is_token_obj2);
739 if (rv != CKR_OK) {
740 goto failed_exit;
741 }
742 obj_nkp.nkp_out_private_count = pri_out_attr_count;
743
744 /*
745 * The public key and the private key need to contain the same
746 * attribute values for CKA_TOKEN.
747 */
748 if (is_token_obj1 != is_token_obj2) {
749 rv = CKR_ATTRIBUTE_VALUE_INVALID;
750 goto failed_exit;
751 }
752
753 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
754 obj_nkp.nkp_session = session_p-> k_session;
755 obj_nkp.nkp_mechanism.cm_type = k_mech_type;
756 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
757 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
758
759 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
760 &obj_nkp)) < 0) {
761 if (errno != EINTR)
762 break;
763 }
764 if (r < 0) {
765 rv = CKR_FUNCTION_FAILED;
766 } else {
767 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
768 }
769 free_attributes(obj_nkp.nkp_in_public_attributes,
770 &obj_nkp.nkp_in_public_count);
771 free_attributes(obj_nkp.nkp_in_private_attributes,
772 &obj_nkp.nkp_in_private_count);
773
774 if (rv != CKR_OK) {
775 goto failed_exit;
776 }
777
778 rv = get_object_attributes(
779 &pubTemplate[pub_attr_count - pub_out_attr_count],
780 pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
781 if (rv == CRYPTO_SUCCESS) {
782 rv = get_object_attributes(
783 &priTemplate[pri_attr_count - pri_out_attr_count],
784 pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
785 }
786 free_attributes(obj_nkp.nkp_out_public_attributes,
787 &obj_nkp.nkp_out_public_count);
788 free_attributes(obj_nkp.nkp_out_private_attributes,
789 &obj_nkp.nkp_out_private_count);
790 if (rv != CRYPTO_SUCCESS) {
791 goto failed_exit;
792 }
793
794 /* store generated modulus and public exponent */
795 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
796 session_p, KERNEL_GEN_KEY);
797 if (rv != CRYPTO_SUCCESS) {
798 goto failed_exit;
799 }
800
801 /*
802 * Copy CKA_PUBLIC_EXPONENT from the public template
803 * to the private template.
804 */
805 rv = copy_attribute(CKA_PUBLIC_EXPONENT, pubTemplate,
806 pub_attr_count, &priTemplate[pri_attr_count]);
807 if (rv != CRYPTO_SUCCESS) {
808 goto failed_exit;
809 }
810
811 rv = kernel_build_object(priTemplate, pri_attr_count + 1, new_pri_objp,
812 session_p, KERNEL_GEN_KEY);
813 (void) free(priTemplate[pri_attr_count].pValue);
814 if (rv != CRYPTO_SUCCESS) {
815 goto failed_exit;
816 }
817 (void) free(pubTemplate);
818 (void) free(priTemplate);
819
820 new_pub_objp->is_lib_obj = B_TRUE;
821 new_pri_objp->is_lib_obj = B_TRUE;
822 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
823 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
824 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
825 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
826 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
827 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
828 return (CKR_OK);
829
830 failed_exit:
831 free_attributes(obj_nkp.nkp_in_public_attributes,
832 &obj_nkp.nkp_in_public_count);
833 free_attributes(obj_nkp.nkp_out_public_attributes,
834 &obj_nkp.nkp_out_public_count);
835 free_attributes(obj_nkp.nkp_in_private_attributes,
836 &obj_nkp.nkp_in_private_count);
837 free_attributes(obj_nkp.nkp_out_private_attributes,
838 &obj_nkp.nkp_out_private_count);
839 if (pubTemplate != NULL) {
840 (void) free(pubTemplate);
841 }
842 if (priTemplate != NULL) {
843 (void) free(priTemplate);
844 }
845 return (rv);
846 }
847
848 CK_RV
key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)849 key_gen_dh_by_value(CK_MECHANISM_PTR pMechanism,
850 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
851 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
852 kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
853 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
854 {
855 crypto_nostore_generate_key_pair_t obj_nkp;
856 CK_ATTRIBUTE_PTR pubTemplate = NULL;
857 CK_ATTRIBUTE_PTR priTemplate = NULL;
858 CK_RV rv = CKR_OK;
859 CK_BBOOL is_token_obj1 = FALSE;
860 CK_BBOOL is_token_obj2 = FALSE;
861 uint_t pub_attr_count, pri_attr_count;
862 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
863 char public_value[256];
864 char private_value[256];
865 CK_ULONG pub_class = CKO_PUBLIC_KEY;
866 CK_ULONG pri_class = CKO_PRIVATE_KEY;
867 CK_ULONG key_type;
868 boolean_t has_class, has_key_type;
869 int n, r;
870
871 obj_nkp.nkp_in_public_count = 0;
872 obj_nkp.nkp_out_public_count = 0;
873 obj_nkp.nkp_in_private_count = 0;
874 obj_nkp.nkp_out_private_count = 0;
875
876 /*
877 * Add CKA_VALUE to the public template.
878 * This attribute must not be in the template.
879 */
880 if (attribute_in_template(CKA_VALUE, pPublicKeyTemplate,
881 ulPublicKeyAttributeCount)) {
882 rv = CKR_TEMPLATE_INCONSISTENT;
883 goto failed_exit;
884 }
885 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
886 ulPublicKeyAttributeCount);
887 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
888 ulPublicKeyAttributeCount);
889
890 pub_attr_count = ulPublicKeyAttributeCount + 1;
891 if (!has_class)
892 pub_attr_count++;
893 if (!has_key_type)
894 pub_attr_count++;
895 pubTemplate = grow_template(pPublicKeyTemplate,
896 ulPublicKeyAttributeCount, pub_attr_count);
897 if (pubTemplate == NULL) {
898 rv = CKR_HOST_MEMORY;
899 goto failed_exit;
900 }
901
902 n = ulPublicKeyAttributeCount;
903 if (!has_class) {
904 pubTemplate[n].type = CKA_CLASS;
905 pubTemplate[n].pValue = (caddr_t)&pub_class;
906 pubTemplate[n].ulValueLen = sizeof (pub_class);
907 n++;
908 }
909 if (!has_key_type) {
910 pubTemplate[n].type = CKA_KEY_TYPE;
911 key_type = CKK_DH;
912 pubTemplate[n].pValue = (caddr_t)&key_type;
913 pubTemplate[n].ulValueLen = sizeof (key_type);
914 n++;
915 }
916 pubTemplate[n].type = CKA_VALUE;
917 pubTemplate[n].pValue = (caddr_t)public_value;
918 pubTemplate[n].ulValueLen = sizeof (public_value);
919 pub_out_attr_count++;
920
921 rv = process_object_attributes(pubTemplate,
922 pub_attr_count - pub_out_attr_count,
923 &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
924 if (rv != CKR_OK) {
925 goto failed_exit;
926 }
927 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
928
929 rv = process_object_attributes(
930 &pubTemplate[pub_attr_count - pub_out_attr_count],
931 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
932 &is_token_obj1);
933 if (rv != CKR_OK) {
934 goto failed_exit;
935 }
936 obj_nkp.nkp_out_public_count = pub_out_attr_count;
937
938 /*
939 * Cannot create a token object with a READ-ONLY
940 * session.
941 */
942 if (is_token_obj1 && session_p->ses_RO) {
943 rv = CKR_SESSION_READ_ONLY;
944 goto failed_exit;
945 }
946
947 /*
948 * CKA_BASE, CKA_PRIME, and CKA_VALUE must not appear
949 * in private template.
950 */
951 if (attribute_in_template(CKA_BASE, pPrivateKeyTemplate,
952 ulPrivateKeyAttributeCount) ||
953 attribute_in_template(CKA_PRIME, pPrivateKeyTemplate,
954 ulPrivateKeyAttributeCount) ||
955 attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
956 ulPrivateKeyAttributeCount)) {
957 rv = CKR_TEMPLATE_INCONSISTENT;
958 goto failed_exit;
959 }
960
961 if (attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
962 ulPrivateKeyAttributeCount)) {
963 rv = CKR_TEMPLATE_INCONSISTENT;
964 goto failed_exit;
965 }
966 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
967 ulPrivateKeyAttributeCount);
968 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
969 ulPrivateKeyAttributeCount);
970
971 pri_attr_count = ulPrivateKeyAttributeCount + 1;
972 if (!has_class)
973 pri_attr_count++;
974 if (!has_key_type)
975 pri_attr_count++;
976
977 /* allocate space for CKA_BASE and CKA_PRIME */
978 priTemplate = grow_template(pPrivateKeyTemplate,
979 ulPrivateKeyAttributeCount, pri_attr_count + 2);
980 if (priTemplate == NULL) {
981 rv = CKR_HOST_MEMORY;
982 goto failed_exit;
983 }
984 n = ulPrivateKeyAttributeCount;
985 if (!has_class) {
986 priTemplate[n].type = CKA_CLASS;
987 priTemplate[n].pValue = (caddr_t)&pri_class;
988 priTemplate[n].ulValueLen = sizeof (pri_class);
989 n++;
990 }
991 if (!has_key_type) {
992 priTemplate[n].type = CKA_KEY_TYPE;
993 key_type = CKK_DH;
994 priTemplate[n].pValue = (caddr_t)&key_type;
995 priTemplate[n].ulValueLen = sizeof (key_type);
996 n++;
997 }
998 priTemplate[n].type = CKA_VALUE;
999 priTemplate[n].pValue = (caddr_t)private_value;
1000 priTemplate[n].ulValueLen = sizeof (private_value);
1001 pri_out_attr_count++;
1002
1003 rv = process_object_attributes(priTemplate,
1004 pri_attr_count - pri_out_attr_count,
1005 &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
1006 if (rv != CKR_OK) {
1007 goto failed_exit;
1008 }
1009 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
1010
1011 rv = process_object_attributes(
1012 &priTemplate[pri_attr_count - pri_out_attr_count],
1013 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
1014 &is_token_obj2);
1015 if (rv != CKR_OK) {
1016 goto failed_exit;
1017 }
1018 obj_nkp.nkp_out_private_count = pri_out_attr_count;
1019
1020 /*
1021 * The public key and the private key need to contain the same
1022 * attribute values for CKA_TOKEN.
1023 */
1024 if (is_token_obj1 != is_token_obj2) {
1025 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1026 goto failed_exit;
1027 }
1028
1029 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1030 obj_nkp.nkp_session = session_p-> k_session;
1031 obj_nkp.nkp_mechanism.cm_type = k_mech_type;
1032 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
1033 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
1034
1035 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
1036 &obj_nkp)) < 0) {
1037 if (errno != EINTR)
1038 break;
1039 }
1040 if (r < 0) {
1041 rv = CKR_FUNCTION_FAILED;
1042 } else {
1043 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
1044 }
1045 free_attributes(obj_nkp.nkp_in_public_attributes,
1046 &obj_nkp.nkp_in_public_count);
1047 free_attributes(obj_nkp.nkp_in_private_attributes,
1048 &obj_nkp.nkp_in_private_count);
1049
1050 if (rv != CKR_OK) {
1051 goto failed_exit;
1052 }
1053
1054 rv = get_object_attributes(
1055 &pubTemplate[pub_attr_count - pub_out_attr_count],
1056 pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
1057 if (rv == CRYPTO_SUCCESS) {
1058 rv = get_object_attributes(
1059 &priTemplate[pri_attr_count - pri_out_attr_count],
1060 pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
1061 }
1062 free_attributes(obj_nkp.nkp_out_public_attributes,
1063 &obj_nkp.nkp_out_public_count);
1064 free_attributes(obj_nkp.nkp_out_private_attributes,
1065 &obj_nkp.nkp_out_private_count);
1066
1067 if (rv != CRYPTO_SUCCESS) {
1068 goto failed_exit;
1069 }
1070
1071 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
1072 session_p, KERNEL_GEN_KEY);
1073 if (rv != CRYPTO_SUCCESS) {
1074 goto failed_exit;
1075 }
1076
1077 /*
1078 * Copy CKA_BASE and CKA_PRIME from the public template
1079 * to the private template.
1080 */
1081 rv = copy_attribute(CKA_BASE, pubTemplate, pub_attr_count,
1082 &priTemplate[pri_attr_count]);
1083 if (rv != CRYPTO_SUCCESS) {
1084 goto failed_exit;
1085 }
1086 rv = copy_attribute(CKA_PRIME, pubTemplate, pub_attr_count,
1087 &priTemplate[pri_attr_count + 1]);
1088 if (rv != CRYPTO_SUCCESS) {
1089 (void) free(priTemplate[pri_attr_count].pValue);
1090 goto failed_exit;
1091 }
1092
1093 /* +2 to account for CKA_BASE and CKA_PRIME */
1094 rv = kernel_build_object(priTemplate, pri_attr_count + 2,
1095 new_pri_objp, session_p, KERNEL_GEN_KEY);
1096 (void) free(priTemplate[pri_attr_count].pValue);
1097 (void) free(priTemplate[pri_attr_count + 1].pValue);
1098 if (rv != CRYPTO_SUCCESS) {
1099 goto failed_exit;
1100 }
1101 (void) free(pubTemplate);
1102 (void) free(priTemplate);
1103
1104 new_pub_objp->is_lib_obj = B_TRUE;
1105 new_pri_objp->is_lib_obj = B_TRUE;
1106 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1107 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1108 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
1109 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1110 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
1111 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1112 return (CKR_OK);
1113
1114 failed_exit:
1115 free_attributes(obj_nkp.nkp_in_public_attributes,
1116 &obj_nkp.nkp_in_public_count);
1117 free_attributes(obj_nkp.nkp_out_public_attributes,
1118 &obj_nkp.nkp_out_public_count);
1119 free_attributes(obj_nkp.nkp_in_private_attributes,
1120 &obj_nkp.nkp_in_private_count);
1121 free_attributes(obj_nkp.nkp_out_private_attributes,
1122 &obj_nkp.nkp_out_private_count);
1123 if (pubTemplate != NULL) {
1124 (void) free(pubTemplate);
1125 }
1126 if (priTemplate != NULL) {
1127 (void) free(priTemplate);
1128 }
1129 return (rv);
1130 }
1131
1132 CK_RV
key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * new_pub_objp,kernel_object_t * new_pri_objp)1133 key_gen_ec_by_value(CK_MECHANISM_PTR pMechanism,
1134 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
1135 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
1136 kernel_session_t *session_p, crypto_mech_type_t k_mech_type,
1137 kernel_object_t *new_pub_objp, kernel_object_t *new_pri_objp)
1138 {
1139 crypto_nostore_generate_key_pair_t obj_nkp;
1140 CK_ATTRIBUTE_PTR pubTemplate = NULL;
1141 CK_ATTRIBUTE_PTR priTemplate = NULL;
1142 CK_RV rv = CKR_OK;
1143 CK_BBOOL is_token_obj1 = FALSE;
1144 CK_BBOOL is_token_obj2 = FALSE;
1145 uint_t pub_attr_count, pri_attr_count;
1146 uint_t pub_out_attr_count = 0, pri_out_attr_count = 0;
1147 char value[EC_MAX_VALUE_LEN];
1148 char point[EC_MAX_POINT_LEN];
1149 CK_ULONG pub_class = CKO_PUBLIC_KEY;
1150 CK_ULONG pri_class = CKO_PRIVATE_KEY;
1151 CK_ULONG key_type;
1152 boolean_t has_class, has_key_type;
1153 int n, r;
1154
1155 obj_nkp.nkp_in_public_count = 0;
1156 obj_nkp.nkp_out_public_count = 0;
1157 obj_nkp.nkp_in_private_count = 0;
1158 obj_nkp.nkp_out_private_count = 0;
1159
1160 /*
1161 * Add CKA_EC_POINT to the public template.
1162 * This is the generated value Q. This attribute
1163 * must not be in the template.
1164 */
1165 if (attribute_in_template(CKA_EC_POINT, pPublicKeyTemplate,
1166 ulPublicKeyAttributeCount)) {
1167 rv = CKR_TEMPLATE_INCONSISTENT;
1168 goto failed_exit;
1169 }
1170 has_class = attribute_in_template(CKA_CLASS, pPublicKeyTemplate,
1171 ulPublicKeyAttributeCount);
1172 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPublicKeyTemplate,
1173 ulPublicKeyAttributeCount);
1174
1175 pub_attr_count = ulPublicKeyAttributeCount + 1;
1176 if (!has_class)
1177 pub_attr_count++;
1178 if (!has_key_type)
1179 pub_attr_count++;
1180 pubTemplate = grow_template(pPublicKeyTemplate,
1181 ulPublicKeyAttributeCount, pub_attr_count);
1182 if (pubTemplate == NULL) {
1183 rv = CKR_HOST_MEMORY;
1184 goto failed_exit;
1185 }
1186
1187 n = ulPublicKeyAttributeCount;
1188 if (!has_class) {
1189 pubTemplate[n].type = CKA_CLASS;
1190 pubTemplate[n].pValue = (caddr_t)&pub_class;
1191 pubTemplate[n].ulValueLen = sizeof (pub_class);
1192 n++;
1193 }
1194 if (!has_key_type) {
1195 pubTemplate[n].type = CKA_KEY_TYPE;
1196 key_type = CKK_EC;
1197 pubTemplate[n].pValue = (caddr_t)&key_type;
1198 pubTemplate[n].ulValueLen = sizeof (key_type);
1199 n++;
1200 }
1201 pubTemplate[n].type = CKA_EC_POINT;
1202 pubTemplate[n].pValue = (caddr_t)point;
1203 pubTemplate[n].ulValueLen = sizeof (point);
1204 pub_out_attr_count++;
1205
1206 rv = process_object_attributes(pubTemplate,
1207 pub_attr_count - pub_out_attr_count,
1208 &obj_nkp.nkp_in_public_attributes, &is_token_obj1);
1209 if (rv != CKR_OK) {
1210 goto failed_exit;
1211 }
1212 obj_nkp.nkp_in_public_count = pub_attr_count - pub_out_attr_count;
1213
1214 rv = process_object_attributes(
1215 &pubTemplate[pub_attr_count - pub_out_attr_count],
1216 pub_out_attr_count, &obj_nkp.nkp_out_public_attributes,
1217 &is_token_obj1);
1218 if (rv != CKR_OK) {
1219 goto failed_exit;
1220 }
1221 obj_nkp.nkp_out_public_count = pub_out_attr_count;
1222
1223 /*
1224 * Cannot create a token object with a READ-ONLY
1225 * session.
1226 */
1227 if (is_token_obj1 && session_p->ses_RO) {
1228 rv = CKR_SESSION_READ_ONLY;
1229 goto failed_exit;
1230 }
1231
1232 /*
1233 * CKA_EC_PARAMS and CKA_VALUE must not appear in
1234 * private template.
1235 */
1236 if (attribute_in_template(CKA_EC_PARAMS, pPrivateKeyTemplate,
1237 ulPrivateKeyAttributeCount) ||
1238 attribute_in_template(CKA_VALUE, pPrivateKeyTemplate,
1239 ulPrivateKeyAttributeCount)) {
1240 rv = CKR_TEMPLATE_INCONSISTENT;
1241 goto failed_exit;
1242 }
1243 has_class = attribute_in_template(CKA_CLASS, pPrivateKeyTemplate,
1244 ulPrivateKeyAttributeCount);
1245 has_key_type = attribute_in_template(CKA_KEY_TYPE, pPrivateKeyTemplate,
1246 ulPrivateKeyAttributeCount);
1247
1248 pri_attr_count = ulPrivateKeyAttributeCount + 1;
1249 if (!has_class)
1250 pri_attr_count++;
1251 if (!has_key_type)
1252 pri_attr_count++;
1253
1254 /* allocate space for CKA_EC_PARAMS */
1255 priTemplate = grow_template(pPrivateKeyTemplate,
1256 ulPrivateKeyAttributeCount, pri_attr_count + 1);
1257 if (priTemplate == NULL) {
1258 rv = CKR_HOST_MEMORY;
1259 goto failed_exit;
1260 }
1261 n = ulPrivateKeyAttributeCount;
1262 if (!has_class) {
1263 priTemplate[n].type = CKA_CLASS;
1264 priTemplate[n].pValue = (caddr_t)&pri_class;
1265 priTemplate[n].ulValueLen = sizeof (pri_class);
1266 n++;
1267 }
1268 if (!has_key_type) {
1269 priTemplate[n].type = CKA_KEY_TYPE;
1270 key_type = CKK_EC;
1271 priTemplate[n].pValue = (caddr_t)&key_type;
1272 priTemplate[n].ulValueLen = sizeof (key_type);
1273 n++;
1274 }
1275 priTemplate[n].type = CKA_VALUE;
1276 priTemplate[n].pValue = (caddr_t)value;
1277 priTemplate[n].ulValueLen = sizeof (value);
1278 pri_out_attr_count++;
1279
1280 rv = process_object_attributes(priTemplate,
1281 pri_attr_count - pri_out_attr_count,
1282 &obj_nkp.nkp_in_private_attributes, &is_token_obj2);
1283 if (rv != CKR_OK) {
1284 goto failed_exit;
1285 }
1286 obj_nkp.nkp_in_private_count = pri_attr_count - pri_out_attr_count;
1287
1288 rv = process_object_attributes(
1289 &priTemplate[pri_attr_count - pri_out_attr_count],
1290 pri_out_attr_count, &obj_nkp.nkp_out_private_attributes,
1291 &is_token_obj2);
1292 if (rv != CKR_OK) {
1293 goto failed_exit;
1294 }
1295 obj_nkp.nkp_out_private_count = pri_out_attr_count;
1296
1297 /*
1298 * The public key and the private key need to contain the same
1299 * attribute values for CKA_TOKEN.
1300 */
1301 if (is_token_obj1 != is_token_obj2) {
1302 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1303 goto failed_exit;
1304 }
1305
1306 /* Call the CRYPTO_NOSTORE_GENERATE_KEY_PAIR ioctl. */
1307 obj_nkp.nkp_session = session_p-> k_session;
1308 obj_nkp.nkp_mechanism.cm_type = k_mech_type;
1309 obj_nkp.nkp_mechanism.cm_param = pMechanism->pParameter;
1310 obj_nkp.nkp_mechanism.cm_param_len = pMechanism->ulParameterLen;
1311
1312 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
1313 &obj_nkp)) < 0) {
1314 if (errno != EINTR)
1315 break;
1316 }
1317 if (r < 0) {
1318 rv = CKR_FUNCTION_FAILED;
1319 } else {
1320 rv = crypto2pkcs11_error_number(obj_nkp.nkp_return_value);
1321 }
1322 free_attributes(obj_nkp.nkp_in_public_attributes,
1323 &obj_nkp.nkp_in_public_count);
1324 free_attributes(obj_nkp.nkp_in_private_attributes,
1325 &obj_nkp.nkp_in_private_count);
1326
1327 if (rv != CKR_OK) {
1328 goto failed_exit;
1329 }
1330
1331 rv = get_object_attributes(
1332 &pubTemplate[pub_attr_count - pub_out_attr_count],
1333 pub_out_attr_count, obj_nkp.nkp_out_public_attributes);
1334 if (rv == CRYPTO_SUCCESS) {
1335 rv = get_object_attributes(
1336 &priTemplate[pri_attr_count - pri_out_attr_count],
1337 pri_out_attr_count, obj_nkp.nkp_out_private_attributes);
1338 }
1339 free_attributes(obj_nkp.nkp_out_public_attributes,
1340 &obj_nkp.nkp_out_public_count);
1341 free_attributes(obj_nkp.nkp_out_private_attributes,
1342 &obj_nkp.nkp_out_private_count);
1343 if (rv != CRYPTO_SUCCESS) {
1344 goto failed_exit;
1345 }
1346
1347 rv = kernel_build_object(pubTemplate, pub_attr_count, new_pub_objp,
1348 session_p, KERNEL_GEN_KEY);
1349 if (rv != CRYPTO_SUCCESS) {
1350 goto failed_exit;
1351 }
1352
1353 /*
1354 * Copy CKA_EC_PARAMS from the public template to the
1355 * private template.
1356 */
1357 rv = copy_attribute(CKA_EC_PARAMS, pubTemplate, pub_attr_count,
1358 &priTemplate[pri_attr_count]);
1359 if (rv != CRYPTO_SUCCESS) {
1360 goto failed_exit;
1361 }
1362
1363 /* +1 to account for CKA_EC_PARAMS */
1364 rv = kernel_build_object(priTemplate, pri_attr_count + 1,
1365 new_pri_objp, session_p, KERNEL_GEN_KEY);
1366 (void) free(priTemplate[pri_attr_count].pValue);
1367 if (rv != CRYPTO_SUCCESS) {
1368 goto failed_exit;
1369 }
1370 (void) free(pubTemplate);
1371 (void) free(priTemplate);
1372
1373 new_pub_objp->is_lib_obj = B_TRUE;
1374 new_pri_objp->is_lib_obj = B_TRUE;
1375 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1376 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1377 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
1378 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1379 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
1380 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1381 return (CKR_OK);
1382
1383 failed_exit:
1384 free_attributes(obj_nkp.nkp_in_public_attributes,
1385 &obj_nkp.nkp_in_public_count);
1386 free_attributes(obj_nkp.nkp_out_public_attributes,
1387 &obj_nkp.nkp_out_public_count);
1388 free_attributes(obj_nkp.nkp_in_private_attributes,
1389 &obj_nkp.nkp_in_private_count);
1390 free_attributes(obj_nkp.nkp_out_private_attributes,
1391 &obj_nkp.nkp_out_private_count);
1392 if (pubTemplate != NULL) {
1393 (void) free(pubTemplate);
1394 }
1395 if (priTemplate != NULL) {
1396 (void) free(priTemplate);
1397 }
1398 return (rv);
1399 }
1400
1401 CK_RV
C_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)1402 C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1403 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
1404 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
1405 CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
1406 {
1407 CK_RV rv = CKR_OK;
1408 kernel_session_t *session_p;
1409 kernel_object_t *new_pub_objp = NULL;
1410 kernel_object_t *new_pri_objp = NULL;
1411 kernel_slot_t *pslot;
1412 boolean_t ses_lock_held = B_FALSE;
1413 CK_BBOOL is_pri_obj1;
1414 CK_BBOOL is_pri_obj2;
1415 CK_BBOOL is_token_obj1 = FALSE;
1416 CK_BBOOL is_token_obj2 = FALSE;
1417 crypto_mech_type_t k_mech_type;
1418 int r;
1419 CK_RV (*func)(CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, CK_ULONG,
1420 CK_ATTRIBUTE_PTR, CK_ULONG, kernel_session_t *, crypto_mech_type_t,
1421 kernel_object_t *, kernel_object_t *);
1422
1423 if (!kernel_initialized)
1424 return (CKR_CRYPTOKI_NOT_INITIALIZED);
1425
1426 /* Obtain the session pointer. */
1427 rv = handle2session(hSession, &session_p);
1428 if (rv != CKR_OK)
1429 return (rv);
1430
1431 if ((pMechanism == NULL) || (phPublicKey == NULL) ||
1432 (phPrivateKey == NULL)) {
1433 rv = CKR_ARGUMENTS_BAD;
1434 goto failed_exit;
1435 }
1436
1437 if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) {
1438 rv = CKR_ARGUMENTS_BAD;
1439 goto failed_exit;
1440 }
1441
1442 if ((pPrivateKeyTemplate == NULL) &&
1443 (ulPrivateKeyAttributeCount != 0)) {
1444 rv = CKR_ARGUMENTS_BAD;
1445 goto failed_exit;
1446 }
1447
1448 /* Get the kernel's internal mechanism number. */
1449 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
1450 if (rv != CKR_OK) {
1451 goto failed_exit;
1452 }
1453
1454 /* Create an object wrapper for the public key */
1455 new_pub_objp = calloc(1, sizeof (kernel_object_t));
1456 if (new_pub_objp == NULL) {
1457 rv = CKR_HOST_MEMORY;
1458 goto failed_exit;
1459 }
1460
1461 /* Create an object wrapper for the private key. */
1462 new_pri_objp = calloc(1, sizeof (kernel_object_t));
1463 if (new_pri_objp == NULL) {
1464 rv = CKR_HOST_MEMORY;
1465 goto failed_exit;
1466 }
1467
1468 /*
1469 * Special Case: if token does not support object creation,
1470 * but does support key generation by value, then create a session
1471 * object and initialize with values returned by token.
1472 */
1473 pslot = slot_table[session_p->ses_slotid];
1474 if (!pslot->sl_func_list.fl_object_create) {
1475 switch (pMechanism->mechanism) {
1476 case CKM_RSA_PKCS_KEY_PAIR_GEN:
1477 func = key_gen_rsa_by_value;
1478 break;
1479
1480 case CKM_DH_PKCS_KEY_PAIR_GEN:
1481 func = key_gen_dh_by_value;
1482 break;
1483
1484 case CKM_EC_KEY_PAIR_GEN:
1485 func = key_gen_ec_by_value;
1486 break;
1487
1488 default:
1489 rv = CKR_MECHANISM_INVALID;
1490 goto failed_exit;
1491 }
1492 rv = (*func)(pMechanism, pPublicKeyTemplate,
1493 ulPublicKeyAttributeCount, pPrivateKeyTemplate,
1494 ulPrivateKeyAttributeCount, session_p, k_mech_type,
1495 new_pub_objp, new_pri_objp);
1496 if (rv != CKR_OK)
1497 goto failed_exit;
1498 } else {
1499 crypto_object_generate_key_pair_t obj_kp;
1500
1501 /* Process the public key attributes. */
1502 rv = process_object_attributes(pPublicKeyTemplate,
1503 ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes,
1504 &is_token_obj1);
1505 if (rv != CKR_OK) {
1506 goto failed_exit;
1507 }
1508
1509 /* Cannot create a token object with a READ-ONLY session. */
1510 if (is_token_obj1 && session_p->ses_RO) {
1511 free_object_attributes(obj_kp.kp_public_attributes,
1512 ulPublicKeyAttributeCount);
1513 rv = CKR_SESSION_READ_ONLY;
1514 goto failed_exit;
1515 }
1516
1517 /* Process the private key attributes. */
1518 rv = process_object_attributes(pPrivateKeyTemplate,
1519 ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes,
1520 &is_token_obj2);
1521 if (rv != CKR_OK) {
1522 free_object_attributes(obj_kp.kp_public_attributes,
1523 ulPublicKeyAttributeCount);
1524 goto failed_exit;
1525 }
1526
1527 /*
1528 * The public key and the private key need to contain the same
1529 * attribute values for CKA_TOKEN.
1530 */
1531 if (is_token_obj1 != is_token_obj2) {
1532 free_object_attributes(obj_kp.kp_public_attributes,
1533 ulPublicKeyAttributeCount);
1534 free_object_attributes(obj_kp.kp_private_attributes,
1535 ulPrivateKeyAttributeCount);
1536 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1537 goto failed_exit;
1538 }
1539
1540 /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */
1541 obj_kp.kp_session = session_p-> k_session;
1542 obj_kp.kp_mechanism.cm_type = k_mech_type;
1543 obj_kp.kp_mechanism.cm_param = pMechanism->pParameter;
1544 obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen;
1545 obj_kp.kp_public_count = ulPublicKeyAttributeCount;
1546 obj_kp.kp_private_count = ulPrivateKeyAttributeCount;
1547
1548 while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR,
1549 &obj_kp)) < 0) {
1550 if (errno != EINTR)
1551 break;
1552 }
1553 if (r < 0) {
1554 rv = CKR_FUNCTION_FAILED;
1555 } else {
1556 rv = crypto2pkcs11_error_number(obj_kp.kp_return_value);
1557 }
1558 free_object_attributes(obj_kp.kp_public_attributes,
1559 ulPublicKeyAttributeCount);
1560 free_object_attributes(obj_kp.kp_private_attributes,
1561 ulPrivateKeyAttributeCount);
1562
1563 if (rv != CKR_OK)
1564 goto failed_exit;
1565
1566 /* Get the CKA_PRIVATE value for the key pair. */
1567 rv = get_cka_private_value(session_p, obj_kp.kp_public_handle,
1568 &is_pri_obj1);
1569 if (rv != CKR_OK) {
1570 goto failed_exit;
1571 }
1572
1573 rv = get_cka_private_value(session_p, obj_kp.kp_private_handle,
1574 &is_pri_obj2);
1575 if (rv != CKR_OK) {
1576 goto failed_exit;
1577 }
1578
1579 /*
1580 * Store the kernel public key handle into the public key
1581 * object and finish the public key object initialization.
1582 */
1583 new_pub_objp->is_lib_obj = B_FALSE;
1584 new_pub_objp->k_handle = obj_kp.kp_public_handle;
1585 new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1586 new_pub_objp->extra_attrlistp = NULL;
1587
1588 if (is_pri_obj1)
1589 new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1590 else
1591 new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1592
1593 if (is_token_obj1)
1594 new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON;
1595 else
1596 new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
1597
1598 (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL);
1599 new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1600
1601 /*
1602 * Store the kernel private key handle into the private key
1603 * object and finish the private key object initialization.
1604 */
1605 new_pri_objp->is_lib_obj = B_FALSE;
1606 new_pri_objp->k_handle = obj_kp.kp_private_handle;
1607 new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1608 new_pri_objp->extra_attrlistp = NULL;
1609
1610 if (is_pri_obj2)
1611 new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1612 else
1613 new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1614
1615 if (is_token_obj2)
1616 new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON;
1617 else
1618 new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
1619
1620 }
1621 (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL);
1622 new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1623
1624 /*
1625 * Add the new pub/pri objects to the slot's token list if they are
1626 * token objects. Otherwise, add them to the session's object list.
1627 */
1628 if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */
1629 pslot = slot_table[session_p->ses_slotid];
1630 kernel_add_token_object_to_slot(new_pub_objp, pslot);
1631 kernel_add_token_object_to_slot(new_pri_objp, pslot);
1632 } else {
1633 kernel_add_object_to_session(new_pub_objp, session_p);
1634 kernel_add_object_to_session(new_pri_objp, session_p);
1635 }
1636
1637 *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp;
1638 *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp;
1639 REFRELE(session_p, ses_lock_held);
1640 return (rv);
1641
1642 failed_exit:
1643 if (new_pub_objp != NULL) {
1644 (void) free(new_pub_objp);
1645 }
1646 if (new_pri_objp != NULL) {
1647 (void) free(new_pri_objp);
1648 }
1649 REFRELE(session_p, ses_lock_held);
1650 return (rv);
1651 }
1652
1653
1654 CK_RV
C_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)1655 C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1656 CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
1657 CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
1658 {
1659 CK_RV rv = CKR_OK;
1660 kernel_session_t *session_p;
1661 boolean_t ses_lock_held = B_FALSE;
1662 kernel_object_t *wrappingkey_p;
1663 kernel_object_t *key_p;
1664 crypto_mech_type_t k_mech_type;
1665 crypto_object_wrap_key_t obj_wrapkey;
1666 int r;
1667
1668 if (!kernel_initialized)
1669 return (CKR_CRYPTOKI_NOT_INITIALIZED);
1670
1671 if (pulWrappedKeyLen == NULL || pMechanism == NULL) {
1672 return (CKR_ARGUMENTS_BAD);
1673 }
1674
1675 /*
1676 * Obtain the session pointer. Also, increment the session
1677 * reference count.
1678 */
1679 rv = handle2session(hSession, &session_p);
1680 if (rv != CKR_OK)
1681 return (rv);
1682
1683 /* Get the kernel's internal mechanism number. */
1684 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
1685 if (rv != CKR_OK) {
1686 REFRELE(session_p, ses_lock_held);
1687 return (rv);
1688 }
1689
1690 /* Obtain the wrapping key object pointer. */
1691 HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv);
1692 if (rv != CKR_OK) {
1693 REFRELE(session_p, ses_lock_held);
1694 return (rv);
1695 }
1696
1697 /* Obtain the to_be_wrapped key object pointer. */
1698 HANDLE2OBJECT(hKey, key_p, rv);
1699 if (rv != CKR_OK) {
1700 OBJ_REFRELE(wrappingkey_p);
1701 REFRELE(session_p, ses_lock_held);
1702 return (rv);
1703 }
1704
1705 /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */
1706 obj_wrapkey.wk_session = session_p->k_session;
1707 obj_wrapkey.wk_mechanism.cm_type = k_mech_type;
1708 obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter;
1709 obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen;
1710 obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
1711 obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle;
1712 obj_wrapkey.wk_object_handle = key_p->k_handle;
1713 obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen;
1714 obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey;
1715
1716 while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) {
1717 if (errno != EINTR)
1718 break;
1719 }
1720 if (r < 0) {
1721 rv = CKR_FUNCTION_FAILED;
1722 } else {
1723 rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value);
1724 }
1725
1726 /*
1727 * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen
1728 * when the applciation-supplied wrapped key buffer is too small.
1729 * The situation that the application only asks for the length of
1730 * the wrapped key is covered in rv == CKR_OK.
1731 */
1732 if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) {
1733 *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len;
1734 }
1735
1736 OBJ_REFRELE(key_p);
1737 OBJ_REFRELE(wrappingkey_p);
1738 REFRELE(session_p, ses_lock_held);
1739 return (rv);
1740 }
1741
1742
1743 CK_RV
C_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)1744 C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
1745 CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
1746 CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
1747 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
1748 {
1749 CK_RV rv = CKR_OK;
1750 kernel_session_t *session_p;
1751 kernel_object_t *unwrappingkey_p;
1752 kernel_object_t *new_objp = NULL;
1753 kernel_slot_t *pslot;
1754 boolean_t ses_lock_held = B_FALSE;
1755 CK_BBOOL is_pri_obj;
1756 CK_BBOOL is_token_obj = FALSE;
1757 CK_MECHANISM_INFO info;
1758 uint32_t k_mi_flags;
1759 CK_BYTE *clear_key_val = NULL;
1760 CK_ULONG ulDataLen;
1761 CK_ATTRIBUTE_PTR newTemplate = NULL;
1762 crypto_mech_type_t k_mech_type;
1763 crypto_object_unwrap_key_t obj_unwrapkey;
1764 int r;
1765
1766 if (!kernel_initialized)
1767 return (CKR_CRYPTOKI_NOT_INITIALIZED);
1768
1769 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) {
1770 return (CKR_ARGUMENTS_BAD);
1771 }
1772
1773 if ((pTemplate == NULL) && (ulAttributeCount != 0)) {
1774 return (CKR_ARGUMENTS_BAD);
1775 }
1776
1777 /* Obtain the session pointer. */
1778 rv = handle2session(hSession, &session_p);
1779 if (rv != CKR_OK)
1780 return (rv);
1781
1782 /* Obtain the wrapping key object pointer. */
1783 HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv);
1784 if (rv != CKR_OK) {
1785 REFRELE(session_p, ses_lock_held);
1786 return (rv);
1787 }
1788
1789 /*
1790 * If the HW provider doesn't support C_UnwrapKey, we will try
1791 * to emulate it in the library.
1792 */
1793 pslot = slot_table[session_p->ses_slotid];
1794 if ((!pslot->sl_func_list.fl_object_create) &&
1795 (!pslot->sl_func_list.fl_key_unwrap)) {
1796 rv = get_mechanism_info(pslot, pMechanism->mechanism, &info,
1797 &k_mi_flags);
1798 if (rv != CKR_OK) {
1799 goto failed_exit;
1800 }
1801
1802 /*
1803 * If the mechanism flag doesn't have CKF_UNWRAP, and it's
1804 * an unwrapping of a secret key object, then help this
1805 * out with a decryption followed by an object creation.
1806 */
1807 if (!(k_mi_flags & CRYPTO_FG_UNWRAP) &&
1808 (k_mi_flags & CRYPTO_FG_DECRYPT) &&
1809 (is_secret_key_template(pTemplate, ulAttributeCount))) {
1810
1811 /* First allocate space for the recovered key value */
1812 clear_key_val = malloc(ulWrappedKeyLen);
1813 if (clear_key_val == NULL) {
1814 rv = CKR_HOST_MEMORY;
1815 goto failed_exit;
1816 }
1817
1818 rv = kernel_decrypt_init(session_p, unwrappingkey_p,
1819 pMechanism);
1820 if (rv != CKR_OK) {
1821 goto failed_exit;
1822 }
1823
1824 ulDataLen = ulWrappedKeyLen;
1825 rv = kernel_decrypt(session_p, pWrappedKey,
1826 ulWrappedKeyLen, clear_key_val, &ulDataLen);
1827 if (rv != CKR_OK) {
1828 goto failed_exit;
1829 }
1830
1831 newTemplate = grow_template(pTemplate, ulAttributeCount,
1832 ulAttributeCount + 1);
1833 if (newTemplate == NULL) {
1834 rv = CKR_HOST_MEMORY;
1835 goto failed_exit;
1836 }
1837 /* Now add the CKA_VALUE attribute to template */
1838 newTemplate[ulAttributeCount].type = CKA_VALUE;
1839 newTemplate[ulAttributeCount].pValue = clear_key_val;
1840 newTemplate[ulAttributeCount].ulValueLen = ulDataLen;
1841
1842 /* Finally create the key, based on the new template */
1843 rv = kernel_add_object(newTemplate,
1844 ulAttributeCount + 1, phKey, session_p);
1845 (void) free(clear_key_val);
1846 (void) free(newTemplate);
1847 OBJ_REFRELE(unwrappingkey_p);
1848 REFRELE(session_p, ses_lock_held);
1849 return (rv);
1850 } else {
1851 rv = CKR_FUNCTION_FAILED;
1852 goto failed_exit;
1853 }
1854 }
1855
1856 /*
1857 * If we come here, the HW provider must have registered the unwrapkey
1858 * entry. Therefore, the unwrap key will be performed in the HW
1859 * provider.
1860 */
1861 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
1862 if (rv != CKR_OK) {
1863 goto failed_exit;
1864 }
1865
1866 /* Create an object wrapper for the new key in the library first */
1867 new_objp = calloc(1, sizeof (kernel_object_t));
1868 if (new_objp == NULL) {
1869 rv = CKR_HOST_MEMORY;
1870 goto failed_exit;
1871 }
1872
1873 /* Process the attributes */
1874 rv = process_object_attributes(pTemplate, ulAttributeCount,
1875 &obj_unwrapkey.uk_attributes, &is_token_obj);
1876 if (rv != CKR_OK) {
1877 goto failed_exit;
1878 }
1879
1880 /* Cannot create a token object with a READ-ONLY session. */
1881 if (is_token_obj && session_p->ses_RO) {
1882 free_object_attributes(obj_unwrapkey.uk_attributes,
1883 ulAttributeCount);
1884 rv = CKR_SESSION_READ_ONLY;
1885 goto failed_exit;
1886 }
1887
1888 /* Make the CRYPTO_UNWRAP_KEY ioctl call. */
1889 obj_unwrapkey.uk_session = session_p->k_session;
1890 obj_unwrapkey.uk_mechanism.cm_type = k_mech_type;
1891 obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter;
1892 obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen;
1893 obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE;
1894 obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle;
1895 obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey;
1896 obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen;
1897 obj_unwrapkey.uk_count = ulAttributeCount;
1898
1899 while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) {
1900 if (errno != EINTR)
1901 break;
1902 }
1903 if (r < 0) {
1904 rv = CKR_FUNCTION_FAILED;
1905 } else {
1906 rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value);
1907 }
1908
1909 free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount);
1910 if (rv != CKR_OK) {
1911 goto failed_exit;
1912 }
1913
1914 /* Get the CKA_PRIVATE value for the unwrapped key. */
1915 rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle,
1916 &is_pri_obj);
1917 if (rv != CKR_OK) {
1918 goto failed_exit;
1919 }
1920
1921 /*
1922 * Store the kernel object handle in the new key object wrapper and
1923 * initialize it.
1924 */
1925 new_objp->k_handle = obj_unwrapkey.uk_object_handle;
1926 new_objp->is_lib_obj = B_FALSE;
1927 new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
1928 new_objp->extra_attrlistp = NULL;
1929
1930 if (is_pri_obj)
1931 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1932 else
1933 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1934
1935 if (is_token_obj)
1936 new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
1937 else
1938 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
1939
1940 (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
1941 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1942
1943 /*
1944 * Add the new object to the slot's token object list if it is a
1945 * a token object. Otherwise, add it to the session's object list.
1946 */
1947 if (is_token_obj) {
1948 pslot = slot_table[session_p->ses_slotid];
1949 kernel_add_token_object_to_slot(new_objp, pslot);
1950 } else {
1951 kernel_add_object_to_session(new_objp, session_p);
1952 }
1953
1954 *phKey = (CK_OBJECT_HANDLE)new_objp;
1955 OBJ_REFRELE(unwrappingkey_p);
1956 REFRELE(session_p, ses_lock_held);
1957 return (rv);
1958
1959 failed_exit:
1960 OBJ_REFRELE(unwrappingkey_p);
1961 if (new_objp != NULL)
1962 (void) free(new_objp);
1963
1964 if (clear_key_val != NULL)
1965 (void) free(clear_key_val);
1966
1967 if (newTemplate != NULL)
1968 (void) free(newTemplate);
1969
1970 REFRELE(session_p, ses_lock_held);
1971 return (rv);
1972 }
1973
1974 /*
1975 * Get sufficient attributes from a base key to pass by value in a
1976 * crypto_key structure. Storage for attributes is allocated.
1977 * For EC public keys, it is CKA_EC_PARAMS and CKA_EC_POINT.
1978 * For EC private keys, it is CKA_EC_PARAMS and CKA_VALUE.
1979 */
1980 static int
get_base_key_attributes(kernel_object_t * base_key,crypto_key_t * key_by_value)1981 get_base_key_attributes(kernel_object_t *base_key, crypto_key_t *key_by_value)
1982 {
1983 CK_ATTRIBUTE tmp;
1984 crypto_object_attribute_t *attrs = NULL;
1985 biginteger_t *big;
1986 int i, count = 0, rv;
1987
1988 switch (base_key->key_type) {
1989 case CKK_EC:
1990 count = 2;
1991 attrs = malloc(count * sizeof (crypto_object_attribute_t));
1992 if (attrs == NULL) {
1993 rv = CKR_HOST_MEMORY;
1994 goto out;
1995 }
1996 bzero(attrs, count * sizeof (crypto_object_attribute_t));
1997
1998 (void) pthread_mutex_lock(&base_key->object_mutex);
1999
2000 if (!base_key->is_lib_obj) {
2001 rv = CRYPTO_ARGUMENTS_BAD;
2002 goto out;
2003 }
2004
2005 if (base_key->class != CKO_PUBLIC_KEY &&
2006 base_key->class != CKO_PRIVATE_KEY) {
2007 rv = CRYPTO_ARGUMENTS_BAD;
2008 goto out;
2009 }
2010
2011 /*
2012 * Both public and private EC keys should have
2013 * a CKA_EC_PARAMS attribute.
2014 */
2015 tmp.type = CKA_EC_PARAMS;
2016 tmp.pValue = NULL;
2017
2018 /* get size of attribute */
2019 rv = kernel_get_attribute(base_key, &tmp);
2020 if (rv != CKR_OK) {
2021 goto out;
2022 }
2023
2024 tmp.pValue = malloc(tmp.ulValueLen);
2025 if (tmp.pValue == NULL) {
2026 rv = CKR_HOST_MEMORY;
2027 goto out;
2028 }
2029 rv = kernel_get_attribute(base_key, &tmp);
2030 if (rv != CKR_OK) {
2031 free(tmp.pValue);
2032 goto out;
2033 }
2034 attrs[0].oa_type = tmp.type;
2035 attrs[0].oa_value = tmp.pValue;
2036 attrs[0].oa_value_len = tmp.ulValueLen;
2037
2038 switch (base_key->class) {
2039 case CKO_PUBLIC_KEY:
2040 big = OBJ_PUB_EC_POINT(base_key);
2041 tmp.type = CKA_EC_POINT;
2042 break;
2043
2044 case CKO_PRIVATE_KEY:
2045 big = OBJ_PRI_EC_VALUE(base_key);
2046 tmp.type = CKA_VALUE;
2047 break;
2048
2049 default:
2050 rv = CKR_ATTRIBUTE_TYPE_INVALID;
2051 goto out;
2052 }
2053 tmp.ulValueLen = big->big_value_len;
2054 tmp.pValue = malloc(tmp.ulValueLen);
2055 if (tmp.pValue == NULL) {
2056 rv = CKR_HOST_MEMORY;
2057 goto out;
2058 }
2059 rv = kernel_get_attribute(base_key, &tmp);
2060 if (rv != CKR_OK) {
2061 free(tmp.pValue);
2062 goto out;
2063 }
2064 attrs[1].oa_type = tmp.type;
2065 attrs[1].oa_value = tmp.pValue;
2066 attrs[1].oa_value_len = tmp.ulValueLen;
2067 key_by_value->ck_attrs = attrs;
2068 key_by_value->ck_count = 2;
2069 break;
2070
2071 case CKK_DH:
2072 count = 3;
2073 attrs = malloc(count * sizeof (crypto_object_attribute_t));
2074 if (attrs == NULL) {
2075 rv = CKR_HOST_MEMORY;
2076 goto out;
2077 }
2078 bzero(attrs, count * sizeof (crypto_object_attribute_t));
2079
2080 (void) pthread_mutex_lock(&base_key->object_mutex);
2081
2082 if (!base_key->is_lib_obj) {
2083 rv = CRYPTO_ARGUMENTS_BAD;
2084 goto out;
2085 }
2086
2087 if (base_key->class != CKO_PRIVATE_KEY) {
2088 rv = CRYPTO_ARGUMENTS_BAD;
2089 goto out;
2090 }
2091 tmp.type = CKA_BASE;
2092 tmp.pValue = NULL;
2093
2094 /* get size of attribute */
2095 rv = kernel_get_attribute(base_key, &tmp);
2096 if (rv != CKR_OK) {
2097 goto out;
2098 }
2099
2100 tmp.pValue = malloc(tmp.ulValueLen);
2101 if (tmp.pValue == NULL) {
2102 rv = CKR_HOST_MEMORY;
2103 goto out;
2104 }
2105 rv = kernel_get_attribute(base_key, &tmp);
2106 if (rv != CKR_OK) {
2107 free(tmp.pValue);
2108 goto out;
2109 }
2110 attrs[0].oa_type = tmp.type;
2111 attrs[0].oa_value = tmp.pValue;
2112 attrs[0].oa_value_len = tmp.ulValueLen;
2113
2114 tmp.type = CKA_PRIME;
2115 tmp.pValue = NULL;
2116
2117 /* get size of attribute */
2118 rv = kernel_get_attribute(base_key, &tmp);
2119 if (rv != CKR_OK) {
2120 goto out;
2121 }
2122
2123 tmp.pValue = malloc(tmp.ulValueLen);
2124 if (tmp.pValue == NULL) {
2125 rv = CKR_HOST_MEMORY;
2126 goto out;
2127 }
2128 rv = kernel_get_attribute(base_key, &tmp);
2129 if (rv != CKR_OK) {
2130 free(tmp.pValue);
2131 goto out;
2132 }
2133 attrs[1].oa_type = tmp.type;
2134 attrs[1].oa_value = tmp.pValue;
2135 attrs[1].oa_value_len = tmp.ulValueLen;
2136
2137 big = OBJ_PRI_DH_VALUE(base_key);
2138 tmp.type = CKA_VALUE;
2139
2140 tmp.ulValueLen = big->big_value_len;
2141 tmp.pValue = malloc(tmp.ulValueLen);
2142 if (tmp.pValue == NULL) {
2143 rv = CKR_HOST_MEMORY;
2144 goto out;
2145 }
2146 rv = kernel_get_attribute(base_key, &tmp);
2147 if (rv != CKR_OK) {
2148 free(tmp.pValue);
2149 goto out;
2150 }
2151 attrs[2].oa_type = tmp.type;
2152 attrs[2].oa_value = tmp.pValue;
2153 attrs[2].oa_value_len = tmp.ulValueLen;
2154 key_by_value->ck_attrs = attrs;
2155 key_by_value->ck_count = 3;
2156 break;
2157
2158 default:
2159 rv = CKR_ATTRIBUTE_TYPE_INVALID;
2160 goto out;
2161 }
2162 (void) pthread_mutex_unlock(&base_key->object_mutex);
2163 return (CKR_OK);
2164
2165 out:
2166 (void) pthread_mutex_unlock(&base_key->object_mutex);
2167 if (attrs != NULL) {
2168 for (i = 0; i < count; i++) {
2169 if (attrs[i].oa_value != NULL)
2170 free(attrs[i].oa_value);
2171 }
2172 free(attrs);
2173 }
2174 return (rv);
2175 }
2176
2177 CK_RV
derive_key_by_value(CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,kernel_session_t * session_p,crypto_mech_type_t k_mech_type,kernel_object_t * basekey_p,kernel_object_t * new_objp)2178 derive_key_by_value(CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate,
2179 CK_ULONG ulAttributeCount, kernel_session_t *session_p,
2180 crypto_mech_type_t k_mech_type, kernel_object_t *basekey_p,
2181 kernel_object_t *new_objp)
2182 {
2183 crypto_nostore_derive_key_t obj_ndk;
2184 char *key_buf = NULL;
2185 CK_ATTRIBUTE_PTR newTemplate = NULL;
2186 CK_BBOOL is_token_obj = FALSE;
2187 CK_RV rv = CKR_OK;
2188 CK_ULONG secret_class = CKO_SECRET_KEY;
2189 ulong_t key_len = 0;
2190 uint_t attr_count = 0;
2191 boolean_t removed;
2192 boolean_t has_class;
2193 int r, n;
2194
2195 obj_ndk.ndk_in_count = 0;
2196 obj_ndk.ndk_out_count = 0;
2197 obj_ndk.ndk_base_key.ck_count = 0;
2198
2199 rv = get_key_len_from_template(pMechanism, pTemplate, ulAttributeCount,
2200 basekey_p, &key_len);
2201 if (rv != CKR_OK) {
2202 goto failed_exit;
2203 }
2204
2205 if ((key_buf = malloc(key_len)) == NULL) {
2206 rv = CKR_HOST_MEMORY;
2207 goto failed_exit;
2208 }
2209
2210 has_class = attribute_in_template(CKA_CLASS, pTemplate,
2211 ulAttributeCount);
2212
2213 attr_count = ulAttributeCount + 1;
2214 if (!has_class)
2215 attr_count++;
2216
2217 newTemplate = grow_template(pTemplate, ulAttributeCount, attr_count);
2218 if (newTemplate == NULL) {
2219 rv = CKR_HOST_MEMORY;
2220 goto failed_exit;
2221 }
2222
2223 n = ulAttributeCount;
2224 if (!has_class) {
2225 newTemplate[n].type = CKA_CLASS;
2226 newTemplate[n].pValue = (caddr_t)&secret_class;
2227 newTemplate[n].ulValueLen = sizeof (secret_class);
2228 n++;
2229 }
2230
2231 /* Add CKA_VALUE to the template */
2232 newTemplate[n].type = CKA_VALUE;
2233 newTemplate[n].pValue = (caddr_t)key_buf;
2234 newTemplate[n].ulValueLen = key_len;
2235
2236 rv = process_object_attributes(newTemplate, attr_count - 1,
2237 &obj_ndk.ndk_in_attributes, &is_token_obj);
2238 if (rv != CKR_OK) {
2239 goto failed_exit;
2240 }
2241 obj_ndk.ndk_in_count = attr_count - 1;
2242
2243 rv = process_object_attributes(&newTemplate[attr_count - 1],
2244 1, &obj_ndk.ndk_out_attributes, &is_token_obj);
2245 if (rv != CKR_OK) {
2246 goto failed_exit;
2247 }
2248 obj_ndk.ndk_out_count = 1;
2249
2250 /* Cannot create a token object with a READ-ONLY session. */
2251 if (is_token_obj && session_p->ses_RO) {
2252 rv = CKR_SESSION_READ_ONLY;
2253 goto failed_exit;
2254 }
2255
2256 obj_ndk.ndk_session = session_p->k_session;
2257 obj_ndk.ndk_mechanism.cm_type = k_mech_type;
2258 obj_ndk.ndk_mechanism.cm_param = pMechanism->pParameter;
2259 obj_ndk.ndk_mechanism.cm_param_len = pMechanism->ulParameterLen;
2260
2261 /*
2262 * Obtain the attributes of base key and pass them by value.
2263 */
2264 rv = get_base_key_attributes(basekey_p, &obj_ndk.ndk_base_key);
2265 if (rv != CKR_OK) {
2266 goto failed_exit;
2267 }
2268
2269 obj_ndk.ndk_base_key.ck_format = CRYPTO_KEY_ATTR_LIST;
2270
2271 while ((r = ioctl(kernel_fd, CRYPTO_NOSTORE_DERIVE_KEY,
2272 &obj_ndk)) < 0) {
2273 if (errno != EINTR)
2274 break;
2275 }
2276 if (r < 0) {
2277 rv = CKR_FUNCTION_FAILED;
2278 } else {
2279 rv = crypto2pkcs11_error_number(obj_ndk.ndk_return_value);
2280 }
2281 free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
2282 free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
2283 &obj_ndk.ndk_base_key.ck_count);
2284 if (rv != CKR_OK) {
2285 goto failed_exit;
2286 }
2287
2288 rv = get_object_attributes(&newTemplate[attr_count - 1],
2289 1, obj_ndk.ndk_out_attributes);
2290 free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
2291 if (rv != CRYPTO_SUCCESS) {
2292 goto failed_exit;
2293 }
2294
2295 removed = remove_one_attribute(newTemplate, CKA_VALUE_LEN,
2296 attr_count, B_FALSE);
2297
2298 rv = kernel_build_object(newTemplate, removed ? attr_count - 1 :
2299 attr_count, new_objp, session_p, KERNEL_GEN_KEY);
2300 if (rv != CRYPTO_SUCCESS) {
2301 goto failed_exit;
2302 }
2303
2304 free(key_buf);
2305 free(newTemplate);
2306 new_objp->is_lib_obj = B_TRUE;
2307 new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
2308 return (CKR_OK);
2309
2310 failed_exit:
2311 if (key_buf != NULL)
2312 free(key_buf);
2313 if (newTemplate != NULL)
2314 free(newTemplate);
2315 free_attributes(obj_ndk.ndk_in_attributes, &obj_ndk.ndk_in_count);
2316 free_attributes(obj_ndk.ndk_out_attributes, &obj_ndk.ndk_out_count);
2317 free_attributes((caddr_t)obj_ndk.ndk_base_key.ck_attrs,
2318 &obj_ndk.ndk_base_key.ck_count);
2319 return (rv);
2320 }
2321
2322 CK_RV
C_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)2323 C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
2324 CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
2325 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
2326 {
2327 CK_RV rv = CKR_OK;
2328 kernel_session_t *session_p;
2329 kernel_object_t *basekey_p;
2330 kernel_object_t *new_objp;
2331 kernel_slot_t *pslot;
2332 boolean_t ses_lock_held = B_FALSE;
2333 CK_BBOOL is_pri_obj;
2334 CK_BBOOL is_token_obj = FALSE;
2335 crypto_mech_type_t k_mech_type;
2336 int r;
2337
2338 if (!kernel_initialized)
2339 return (CKR_CRYPTOKI_NOT_INITIALIZED);
2340
2341 /* Obtain the session pointer. */
2342 rv = handle2session(hSession, &session_p);
2343 if (rv != CKR_OK)
2344 return (rv);
2345
2346 if (pMechanism == NULL) {
2347 REFRELE(session_p, ses_lock_held);
2348 return (CKR_ARGUMENTS_BAD);
2349 }
2350
2351 if ((pTemplate == NULL && ulAttributeCount != 0) ||
2352 (pTemplate != NULL && ulAttributeCount == 0)) {
2353 REFRELE(session_p, ses_lock_held);
2354 return (CKR_ARGUMENTS_BAD);
2355 }
2356
2357 /* Obtain the base key object pointer. */
2358 HANDLE2OBJECT(hBaseKey, basekey_p, rv);
2359 if (rv != CKR_OK) {
2360 REFRELE(session_p, ses_lock_held);
2361 return (rv);
2362 }
2363
2364 /* Get the kernel's internal mechanism number. */
2365 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
2366 if (rv != CKR_OK) {
2367 goto failed_exit;
2368 }
2369
2370 /* Create an object wrapper in the library for the generated key. */
2371 new_objp = calloc(1, sizeof (kernel_object_t));
2372 if (new_objp == NULL) {
2373 rv = CKR_HOST_MEMORY;
2374 goto failed_exit;
2375 }
2376
2377 /*
2378 * Special Case: if token does not support object creation,
2379 * but does support key derivation by value, then create a session
2380 * object and initialize with values returned by token.
2381 */
2382 pslot = slot_table[session_p->ses_slotid];
2383 if (!pslot->sl_func_list.fl_object_create) {
2384 rv = derive_key_by_value(pMechanism, pTemplate,
2385 ulAttributeCount, session_p, k_mech_type, basekey_p,
2386 new_objp);
2387 if (rv != CKR_OK)
2388 goto failed_exit;
2389 } else {
2390 crypto_derive_key_t obj_dk;
2391
2392 rv = process_object_attributes(pTemplate, ulAttributeCount,
2393 &obj_dk.dk_attributes, &is_token_obj);
2394 if (rv != CKR_OK) {
2395 goto failed_exit;
2396 }
2397
2398 /* Cannot create a token object with a READ-ONLY session. */
2399 if (is_token_obj && session_p->ses_RO) {
2400 free_object_attributes(obj_dk.dk_attributes,
2401 ulAttributeCount);
2402 rv = CKR_SESSION_READ_ONLY;
2403 goto failed_exit;
2404 }
2405
2406 obj_dk.dk_session = session_p->k_session;
2407 obj_dk.dk_mechanism.cm_type = k_mech_type;
2408 obj_dk.dk_mechanism.cm_param = pMechanism->pParameter;
2409 obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen;
2410 obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE;
2411 obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle;
2412 obj_dk.dk_count = ulAttributeCount;
2413
2414 while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) {
2415 if (errno != EINTR)
2416 break;
2417 }
2418 if (r < 0) {
2419 rv = CKR_FUNCTION_FAILED;
2420 } else {
2421 rv = crypto2pkcs11_error_number(obj_dk.dk_return_value);
2422 }
2423
2424 free_object_attributes(obj_dk.dk_attributes, ulAttributeCount);
2425 if (rv != CKR_OK) {
2426 goto failed_exit;
2427 }
2428
2429 /* Get the CKA_PRIVATE value for the derived key. */
2430 rv = get_cka_private_value(session_p, obj_dk.dk_object_handle,
2431 &is_pri_obj);
2432 if (rv != CKR_OK) {
2433 goto failed_exit;
2434 }
2435
2436 /*
2437 * Store the kernel object handle into the new derived key
2438 * object and finish the object initialization.
2439 */
2440 new_objp->is_lib_obj = B_FALSE;
2441 new_objp->k_handle = obj_dk.dk_object_handle;
2442 new_objp->session_handle = (CK_SESSION_HANDLE)session_p;
2443 new_objp->extra_attrlistp = NULL;
2444
2445 if (is_pri_obj)
2446 new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
2447 else
2448 new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
2449
2450 if (is_token_obj)
2451 new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
2452 else
2453 new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
2454 }
2455 (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
2456 new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
2457
2458 /*
2459 * Add the new derived object to the slot's token list if it is a
2460 * token object. Otherwise, add it to the session's object list.
2461 */
2462 if (is_token_obj) {
2463 pslot = slot_table[session_p->ses_slotid];
2464 kernel_add_token_object_to_slot(new_objp, pslot);
2465 } else {
2466 kernel_add_object_to_session(new_objp, session_p);
2467 }
2468
2469 *phKey = (CK_OBJECT_HANDLE)new_objp;
2470 OBJ_REFRELE(basekey_p);
2471 REFRELE(session_p, ses_lock_held);
2472 return (rv);
2473
2474 failed_exit:
2475 OBJ_REFRELE(basekey_p);
2476 if (new_objp != NULL) {
2477 (void) free(new_objp);
2478 }
2479
2480 REFRELE(session_p, ses_lock_held);
2481 return (rv);
2482 }
2483