1 /*
2 * The Initial Developer of the Original Code is International
3 * Business Machines Corporation. Portions created by IBM
4 * Corporation are Copyright (C) 2005 International Business
5 * Machines Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the Common Public License as published by
9 * IBM Corporation; either version 1 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * Common Public License for more details.
16 *
17 * You should have received a copy of the Common Public License
18 * along with this program; if not, a copy can be viewed at
19 * http://www.opensource.org/licenses/cpl1.0.php.
20 */
21 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "tpmtok_int.h"
28
29 static CK_BBOOL true = TRUE, false = FALSE;
30
31 static CK_RV
key_mgr_get_private_key_type(CK_BYTE * keydata,CK_ULONG keylen,CK_KEY_TYPE * keytype)32 key_mgr_get_private_key_type(
33 CK_BYTE *keydata,
34 CK_ULONG keylen,
35 CK_KEY_TYPE *keytype)
36 {
37 CK_BYTE *alg = NULL;
38 CK_BYTE *priv_key = NULL;
39 CK_ULONG alg_len;
40 CK_RV rc;
41
42 rc = ber_decode_PrivateKeyInfo(keydata, keylen, &alg,
43 &alg_len, &priv_key);
44 if (rc != CKR_OK) {
45 return (rc);
46 }
47 if (alg_len >= ber_rsaEncryptionLen) {
48 if (memcmp(alg, ber_rsaEncryption,
49 ber_rsaEncryptionLen) == 0) {
50 *keytype = CKK_RSA;
51 return (CKR_OK);
52 }
53 }
54
55 return (CKR_TEMPLATE_INCOMPLETE);
56 }
57
58 CK_RV
key_mgr_generate_key_pair(SESSION * sess,CK_MECHANISM * mech,CK_ATTRIBUTE * publ_tmpl,CK_ULONG publ_count,CK_ATTRIBUTE * priv_tmpl,CK_ULONG priv_count,CK_OBJECT_HANDLE * publ_key_handle,CK_OBJECT_HANDLE * priv_key_handle)59 key_mgr_generate_key_pair(SESSION * sess,
60 CK_MECHANISM * mech,
61 CK_ATTRIBUTE * publ_tmpl,
62 CK_ULONG publ_count,
63 CK_ATTRIBUTE * priv_tmpl,
64 CK_ULONG priv_count,
65 CK_OBJECT_HANDLE * publ_key_handle,
66 CK_OBJECT_HANDLE * priv_key_handle)
67 {
68 OBJECT * publ_key_obj = NULL;
69 OBJECT * priv_key_obj = NULL;
70 CK_ATTRIBUTE * attr = NULL;
71 CK_ATTRIBUTE * new_attr = NULL;
72 CK_ULONG i, keyclass, subclass = 0;
73 CK_BBOOL flag;
74 CK_RV rc;
75
76 if (! sess || ! mech || ! publ_key_handle || ! priv_key_handle) {
77 return (CKR_FUNCTION_FAILED);
78 }
79 if (! publ_tmpl && (publ_count != 0)) {
80 return (CKR_FUNCTION_FAILED);
81 }
82 if (! priv_tmpl && (priv_count != 0)) {
83 return (CKR_FUNCTION_FAILED);
84 }
85
86 for (i = 0; i < publ_count; i++) {
87 if (publ_tmpl[i].type == CKA_CLASS) {
88 keyclass = *(CK_OBJECT_CLASS *)publ_tmpl[i].pValue;
89 if (keyclass != CKO_PUBLIC_KEY) {
90 return (CKR_TEMPLATE_INCONSISTENT);
91 }
92 }
93
94 if (publ_tmpl[i].type == CKA_KEY_TYPE)
95 subclass = *(CK_ULONG *)publ_tmpl[i].pValue;
96 }
97
98
99 for (i = 0; i < priv_count; i++) {
100 if (priv_tmpl[i].type == CKA_CLASS) {
101 keyclass = *(CK_OBJECT_CLASS *)priv_tmpl[i].pValue;
102 if (keyclass != CKO_PRIVATE_KEY) {
103 return (CKR_TEMPLATE_INCONSISTENT);
104 }
105 }
106
107 if (priv_tmpl[i].type == CKA_KEY_TYPE) {
108 CK_ULONG temp = *(CK_ULONG *)priv_tmpl[i].pValue;
109 if (temp != subclass) {
110 return (CKR_TEMPLATE_INCONSISTENT);
111 }
112 }
113 }
114
115
116 switch (mech->mechanism) {
117 case CKM_RSA_PKCS_KEY_PAIR_GEN:
118 if (subclass != 0 && subclass != CKK_RSA) {
119 return (CKR_TEMPLATE_INCONSISTENT);
120 }
121
122 subclass = CKK_RSA;
123 break;
124
125 default:
126 return (CKR_MECHANISM_INVALID);
127 }
128
129
130 rc = object_mgr_create_skel(sess,
131 publ_tmpl, publ_count, MODE_KEYGEN,
132 CKO_PUBLIC_KEY, subclass, &publ_key_obj);
133
134 if (rc != CKR_OK) {
135 goto error;
136 }
137 rc = object_mgr_create_skel(sess,
138 priv_tmpl, priv_count, MODE_KEYGEN,
139 CKO_PRIVATE_KEY, subclass, &priv_key_obj);
140
141 if (rc != CKR_OK) {
142 goto error;
143 }
144
145 switch (mech->mechanism) {
146 case CKM_RSA_PKCS_KEY_PAIR_GEN:
147 rc = ckm_rsa_key_pair_gen(
148 sess->hContext,
149 publ_key_obj->template,
150 priv_key_obj->template);
151 break;
152
153 default:
154 rc = CKR_MECHANISM_INVALID;
155 break;
156 }
157
158 if (rc != CKR_OK) {
159 goto error;
160 }
161
162 /*
163 * we can now set CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE
164 * to their appropriate values. this only applies to CKO_SECRET_KEY
165 * and CKO_PRIVATE_KEY objects
166 */
167 flag = template_attribute_find(priv_key_obj->template,
168 CKA_SENSITIVE, &attr);
169 if (flag == TRUE) {
170 flag = *(CK_BBOOL *)attr->pValue;
171
172 rc = build_attribute(CKA_ALWAYS_SENSITIVE, &flag,
173 sizeof (CK_BBOOL), &new_attr);
174 if (rc != CKR_OK) {
175 goto error;
176 }
177 (void) template_update_attribute(priv_key_obj->template,
178 new_attr);
179
180 } else {
181 rc = CKR_FUNCTION_FAILED;
182 goto error;
183 }
184
185
186 flag = template_attribute_find(priv_key_obj->template,
187 CKA_EXTRACTABLE, &attr);
188 if (flag == TRUE) {
189 flag = *(CK_BBOOL *)attr->pValue;
190
191 rc = build_attribute(CKA_NEVER_EXTRACTABLE, &true,
192 sizeof (CK_BBOOL), &new_attr);
193 if (rc != CKR_OK) {
194 goto error;
195 }
196 if (flag == TRUE)
197 *(CK_BBOOL *)new_attr->pValue = false;
198
199 (void) template_update_attribute(priv_key_obj->template,
200 new_attr);
201
202 } else {
203 rc = CKR_FUNCTION_FAILED;
204 goto error;
205 }
206
207 rc = object_mgr_create_final(sess, publ_key_obj, publ_key_handle);
208 if (rc != CKR_OK) {
209 goto error;
210 }
211 rc = object_mgr_create_final(sess, priv_key_obj, priv_key_handle);
212 if (rc != CKR_OK) {
213 (void) object_mgr_destroy_object(sess, *publ_key_handle);
214 publ_key_obj = NULL;
215 goto error;
216 }
217 return (rc);
218
219 error:
220 if (publ_key_obj)
221 (void) object_free(publ_key_obj);
222 if (priv_key_obj)
223 (void) object_free(priv_key_obj);
224
225 *publ_key_handle = 0;
226 *priv_key_handle = 0;
227
228 return (rc);
229 }
230
231 CK_RV
key_mgr_wrap_key(SESSION * sess,CK_BBOOL length_only,CK_MECHANISM * mech,CK_OBJECT_HANDLE h_wrapping_key,CK_OBJECT_HANDLE h_key,CK_BYTE * wrapped_key,CK_ULONG * wrapped_key_len)232 key_mgr_wrap_key(SESSION * sess,
233 CK_BBOOL length_only,
234 CK_MECHANISM * mech,
235 CK_OBJECT_HANDLE h_wrapping_key,
236 CK_OBJECT_HANDLE h_key,
237 CK_BYTE * wrapped_key,
238 CK_ULONG * wrapped_key_len) {
239 ENCR_DECR_CONTEXT * ctx = NULL;
240 OBJECT * key1_obj = NULL;
241 OBJECT * key2_obj = NULL;
242 CK_ATTRIBUTE * attr = NULL;
243 CK_BYTE * data = NULL;
244 CK_ULONG data_len;
245 CK_OBJECT_CLASS class;
246 CK_KEY_TYPE keytype;
247 CK_BBOOL flag;
248 CK_RV rc;
249
250 if (! sess || ! wrapped_key_len) {
251 return (CKR_FUNCTION_FAILED);
252 }
253
254 rc = object_mgr_find_in_map1(sess->hContext, h_wrapping_key, &key1_obj);
255 if (rc != CKR_OK) {
256 return (CKR_WRAPPING_KEY_HANDLE_INVALID);
257 }
258 rc = object_mgr_find_in_map1(sess->hContext, h_key, &key2_obj);
259 if (rc != CKR_OK) {
260 return (CKR_KEY_HANDLE_INVALID);
261 }
262
263 rc = template_attribute_find(key2_obj->template,
264 CKA_EXTRACTABLE, &attr);
265 if (rc == FALSE) {
266 return (CKR_KEY_NOT_WRAPPABLE);
267 } else {
268 flag = *(CK_BBOOL *)attr->pValue;
269 if (flag == FALSE) {
270 return (CKR_KEY_NOT_WRAPPABLE);
271 }
272 }
273
274 rc = template_attribute_find(key2_obj->template, CKA_CLASS, &attr);
275 if (rc == FALSE) {
276 return (CKR_KEY_NOT_WRAPPABLE);
277 } else
278 class = *(CK_OBJECT_CLASS *)attr->pValue;
279
280 switch (mech->mechanism) {
281 case CKM_RSA_PKCS:
282 if (class != CKO_SECRET_KEY) {
283 return (CKR_KEY_NOT_WRAPPABLE);
284 }
285 break;
286
287 default:
288 return (CKR_KEY_NOT_WRAPPABLE);
289 }
290
291 rc = template_attribute_find(key2_obj->template,
292 CKA_KEY_TYPE, &attr);
293 if (rc == FALSE)
294 return (CKR_KEY_NOT_WRAPPABLE);
295 else
296 keytype = *(CK_KEY_TYPE *)attr->pValue;
297
298 switch (keytype) {
299 case CKK_RSA:
300 rc = rsa_priv_wrap_get_data(key2_obj->template, length_only,
301 &data, &data_len);
302 if (rc != CKR_OK) {
303 return (rc);
304 }
305 break;
306
307 case CKK_GENERIC_SECRET:
308 rc = generic_secret_wrap_get_data(key2_obj->template,
309 length_only, &data, &data_len);
310 if (rc != CKR_OK) {
311 return (rc);
312 }
313 break;
314 default:
315 return (CKR_KEY_NOT_WRAPPABLE);
316 }
317
318 switch (mech->mechanism) {
319 case CKM_RSA_PKCS:
320 break;
321
322 default:
323 return (CKR_KEY_NOT_WRAPPABLE);
324 }
325
326 ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT));
327 if (! ctx) {
328 return (CKR_HOST_MEMORY);
329 }
330 (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT));
331
332 rc = encr_mgr_init(sess, ctx, OP_WRAP, mech, h_wrapping_key);
333 if (rc != CKR_OK) {
334 return (rc);
335 }
336 rc = encr_mgr_encrypt(sess, length_only,
337 ctx, data, data_len, wrapped_key, wrapped_key_len);
338
339 if (data != NULL) {
340 free(data);
341 }
342 (void) encr_mgr_cleanup(ctx);
343 free(ctx);
344
345 return (rc);
346 }
347
348 CK_RV
key_mgr_unwrap_key(SESSION * sess,CK_MECHANISM * mech,CK_ATTRIBUTE * attributes,CK_ULONG attrib_count,CK_BYTE * wrapped_key,CK_ULONG wrapped_key_len,CK_OBJECT_HANDLE h_unwrapping_key,CK_OBJECT_HANDLE * h_unwrapped_key)349 key_mgr_unwrap_key(SESSION * sess,
350 CK_MECHANISM * mech,
351 CK_ATTRIBUTE * attributes,
352 CK_ULONG attrib_count,
353 CK_BYTE * wrapped_key,
354 CK_ULONG wrapped_key_len,
355 CK_OBJECT_HANDLE h_unwrapping_key,
356 CK_OBJECT_HANDLE * h_unwrapped_key)
357 {
358 ENCR_DECR_CONTEXT * ctx = NULL;
359 OBJECT * key_obj = NULL;
360 CK_BYTE * data = NULL;
361 CK_ULONG data_len;
362 CK_ULONG keyclass, keytype;
363 CK_ULONG i;
364 CK_BBOOL found_class, found_type, fromend;
365 CK_RV rc;
366
367
368 if (! sess || ! wrapped_key || ! h_unwrapped_key) {
369 return (CKR_FUNCTION_FAILED);
370 }
371
372 rc = object_mgr_find_in_map1(sess->hContext, h_unwrapping_key,
373 &key_obj);
374 if (rc != CKR_OK) {
375 return (CKR_WRAPPING_KEY_HANDLE_INVALID);
376 }
377
378 found_class = FALSE;
379 found_type = FALSE;
380
381 switch (mech->mechanism) {
382 case CKM_RSA_PKCS:
383 keyclass = CKO_SECRET_KEY;
384 found_class = TRUE;
385 break;
386 }
387
388 for (i = 0; i < attrib_count; i++) {
389 switch (attributes[i].type) {
390 case CKA_CLASS:
391 keyclass = *(CK_OBJECT_CLASS *)attributes[i].pValue;
392 found_class = TRUE;
393 break;
394
395 case CKA_KEY_TYPE:
396 keytype = *(CK_KEY_TYPE *)attributes[i].pValue;
397 found_type = TRUE;
398 break;
399 }
400 }
401
402 if (found_class == FALSE || (found_type == FALSE && keyclass !=
403 CKO_PRIVATE_KEY)) {
404 return (CKR_TEMPLATE_INCOMPLETE);
405 }
406
407 switch (mech->mechanism) {
408 case CKM_RSA_PKCS:
409 if (keyclass != CKO_SECRET_KEY) {
410 return (CKR_TEMPLATE_INCONSISTENT);
411 }
412 break;
413 default:
414 return (CKR_MECHANISM_INVALID);
415 }
416
417
418 ctx = (ENCR_DECR_CONTEXT *)malloc(sizeof (ENCR_DECR_CONTEXT));
419 if (! ctx) {
420 return (CKR_HOST_MEMORY);
421 }
422 (void) memset(ctx, 0x0, sizeof (ENCR_DECR_CONTEXT));
423
424 rc = decr_mgr_init(sess, ctx, OP_UNWRAP, mech, h_unwrapping_key);
425 if (rc != CKR_OK)
426 return (rc);
427
428 rc = decr_mgr_decrypt(sess,
429 TRUE, ctx, wrapped_key, wrapped_key_len,
430 data, &data_len);
431 if (rc != CKR_OK) {
432 goto error;
433 }
434 data = (CK_BYTE *)malloc(data_len);
435 if (! data) {
436 rc = CKR_HOST_MEMORY;
437 goto error;
438 }
439
440 rc = decr_mgr_decrypt(sess,
441 FALSE, ctx, wrapped_key, wrapped_key_len,
442 data, &data_len);
443
444 (void) decr_mgr_cleanup(ctx);
445 free(ctx);
446
447 if (rc != CKR_OK) {
448 goto error;
449 }
450 /*
451 * if we use X.509, the data will be padded from the front with zeros.
452 * PKCS #11 specifies that for this mechanism, CK_VALUE is to be read
453 * from the end of the data.
454 *
455 * Note: the PKCS #11 reference implementation gets this wrong.
456 */
457 if (mech->mechanism == CKM_RSA_X_509)
458 fromend = TRUE;
459 else
460 fromend = FALSE;
461
462 if (keyclass == CKO_PRIVATE_KEY) {
463 rc = key_mgr_get_private_key_type(data, data_len, &keytype);
464 if (rc != CKR_OK) {
465 goto error;
466 }
467 }
468
469 rc = object_mgr_create_skel(sess,
470 attributes, attrib_count,
471 MODE_UNWRAP, keyclass, keytype,
472 &key_obj);
473 if (rc != CKR_OK) {
474 goto error;
475 }
476 switch (keyclass) {
477 case CKO_SECRET_KEY:
478 rc = secret_key_unwrap(key_obj->template, keytype, data,
479 data_len, fromend);
480 break;
481
482 case CKO_PRIVATE_KEY:
483 rc = priv_key_unwrap(key_obj->template, keytype,
484 data, data_len);
485 break;
486
487 default:
488 rc = CKR_WRAPPED_KEY_INVALID;
489 break;
490 }
491
492 if (rc != CKR_OK) {
493 goto error;
494 }
495 rc = object_mgr_create_final(sess, key_obj, h_unwrapped_key);
496 if (rc != CKR_OK) {
497 goto error;
498 }
499 if (data) free(data);
500 return (rc);
501
502 error:
503 if (key_obj) (void) object_free(key_obj);
504 if (data) free(data);
505
506 return (rc);
507 }
508