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