1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Key Management Functions
28 * (as defined in PKCS#11 spec section 11.14)
29 */
30
31 #include "metaGlobal.h"
32
33
34 /*
35 * meta_GenerateKey
36 *
37 */
38 CK_RV
meta_GenerateKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phKey)39 meta_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
40 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
41 {
42 CK_RV rv;
43 meta_session_t *session;
44 meta_object_t *key = NULL;
45
46 if (pMechanism == NULL || phKey == NULL)
47 return (CKR_ARGUMENTS_BAD);
48
49 rv = meta_handle2session(hSession, &session);
50 if (rv != CKR_OK)
51 return (rv);
52
53
54 rv = meta_object_alloc(session, &key);
55 if (rv != CKR_OK)
56 goto finish;
57
58 rv = meta_generate_keys(session, pMechanism, pTemplate, ulCount, key,
59 NULL, 0, NULL);
60 if (rv != CKR_OK)
61 goto finish;
62
63 meta_object_activate(key);
64
65 *phKey = (CK_OBJECT_HANDLE) key;
66
67 finish:
68 if (rv != CKR_OK) {
69 if (key)
70 (void) meta_object_dealloc(session, key, B_TRUE);
71 }
72
73 REFRELEASE(session);
74
75 return (rv);
76 }
77
78
79 /*
80 * meta_GenerateKeyPair
81 *
82 */
83 CK_RV
meta_GenerateKeyPair(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pPublicKeyTemplate,CK_ULONG ulPublicKeyAttributeCount,CK_ATTRIBUTE_PTR pPrivateKeyTemplate,CK_ULONG ulPrivateKeyAttributeCount,CK_OBJECT_HANDLE_PTR phPublicKey,CK_OBJECT_HANDLE_PTR phPrivateKey)84 meta_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
85 CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount,
86 CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount,
87 CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
88 {
89 CK_RV rv;
90 meta_session_t *session;
91 meta_object_t *key1 = NULL, *key2 = NULL;
92
93 if (pMechanism == NULL || phPublicKey == NULL || phPrivateKey == NULL)
94 return (CKR_ARGUMENTS_BAD);
95
96 rv = meta_handle2session(hSession, &session);
97 if (rv != CKR_OK)
98 return (rv);
99
100
101 rv = meta_object_alloc(session, &key1);
102 if (rv != CKR_OK)
103 goto finish;
104
105 rv = meta_object_alloc(session, &key2);
106 if (rv != CKR_OK)
107 goto finish;
108
109 rv = meta_generate_keys(session, pMechanism,
110 pPublicKeyTemplate, ulPublicKeyAttributeCount, key1,
111 pPrivateKeyTemplate, ulPrivateKeyAttributeCount, key2);
112 if (rv != CKR_OK)
113 goto finish;
114
115 meta_object_activate(key1);
116 meta_object_activate(key2);
117
118 *phPublicKey = (CK_OBJECT_HANDLE) key1;
119 *phPrivateKey = (CK_OBJECT_HANDLE) key2;
120
121 finish:
122 if (rv != CKR_OK) {
123 if (key1)
124 (void) meta_object_dealloc(session, key1, B_TRUE);
125 if (key2)
126 (void) meta_object_dealloc(session, key2, B_TRUE);
127 }
128
129 REFRELEASE(session);
130
131 return (rv);
132 }
133
134
135 /*
136 * meta_WrapKey
137 *
138 */
139 CK_RV
meta_WrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hWrappingKey,CK_OBJECT_HANDLE hKey,CK_BYTE_PTR pWrappedKey,CK_ULONG_PTR pulWrappedKeyLen)140 meta_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
141 CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey,
142 CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen)
143 {
144 CK_RV rv;
145 meta_session_t *session;
146 meta_object_t *wrappingKey, *inputKey;
147
148 if (pMechanism == NULL || pulWrappedKeyLen == NULL)
149 return (CKR_ARGUMENTS_BAD);
150
151 rv = meta_handle2session(hSession, &session);
152 if (rv != CKR_OK)
153 return (rv);
154
155 rv = meta_handle2object(hKey, &inputKey);
156 if (rv != CKR_OK) {
157 REFRELEASE(session);
158 return (rv);
159 }
160
161 rv = meta_handle2object(hWrappingKey, &wrappingKey);
162 if (rv != CKR_OK) {
163 OBJRELEASE(inputKey);
164 REFRELEASE(session);
165 return (rv);
166 }
167
168 rv = meta_wrap_key(session, pMechanism, wrappingKey,
169 inputKey, pWrappedKey, pulWrappedKeyLen);
170
171 OBJRELEASE(inputKey);
172 OBJRELEASE(wrappingKey);
173 REFRELEASE(session);
174
175 return (rv);
176 }
177
178
179 /*
180 * meta_UnwrapKey
181 *
182 */
183 CK_RV
meta_UnwrapKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hUnwrappingKey,CK_BYTE_PTR pWrappedKey,CK_ULONG ulWrappedKeyLen,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)184 meta_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
185 CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
186 CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
187 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
188 {
189 CK_RV rv;
190 meta_session_t *session;
191 meta_object_t *unwrappingKey, *outputKey = NULL;
192
193 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL)
194 return (CKR_ARGUMENTS_BAD);
195
196 rv = meta_handle2session(hSession, &session);
197 if (rv != CKR_OK)
198 return (rv);
199
200 rv = meta_handle2object(hUnwrappingKey, &unwrappingKey);
201 if (rv != CKR_OK) {
202 REFRELEASE(session);
203 return (rv);
204 }
205
206 rv = meta_object_alloc(session, &outputKey);
207 if (rv != CKR_OK)
208 goto finish;
209
210 (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount,
211 &(outputKey->isToken));
212
213 rv = meta_unwrap_key(session, pMechanism, unwrappingKey,
214 pWrappedKey, ulWrappedKeyLen,
215 pTemplate, ulAttributeCount, outputKey);
216 if (rv != CKR_OK)
217 goto finish;
218
219 meta_object_activate(outputKey);
220
221 *phKey = (CK_OBJECT_HANDLE) outputKey;
222
223 finish:
224 if (rv != CKR_OK) {
225 if (outputKey)
226 (void) meta_object_dealloc(session, outputKey, B_TRUE);
227 }
228
229 OBJRELEASE(unwrappingKey);
230 REFRELEASE(session);
231
232 return (rv);
233 }
234
235
236 /*
237 * meta_DeriveKey
238 *
239 * This function is a bit gross because of PKCS#11 kludges that pass extra
240 * object handles in some mechanism parameters. It probably needs to be
241 * broken up into more managable pieces.
242 */
243 CK_RV
meta_DeriveKey(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hBaseKey,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_OBJECT_HANDLE_PTR phKey)244 meta_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
245 CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
246 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
247 {
248 CK_RV rv;
249 CK_MECHANISM *pMech = pMechanism;
250 meta_session_t *session;
251 meta_object_t *basekey1 = NULL, *basekey2 = NULL;
252 meta_object_t *newKey1 = NULL, *newKey2 = NULL, *newKey3 = NULL,
253 *newKey4 = NULL;
254 boolean_t ssl_keys = B_FALSE;
255 boolean_t tlsprf = B_FALSE;
256
257 CK_MECHANISM metaMech;
258 CK_OBJECT_HANDLE *phBaseKey2 = NULL;
259 CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr;
260 CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr;
261 CK_SSL3_KEY_MAT_OUT *ssl_key_mat;
262 CK_SSL3_KEY_MAT_PARAMS *keyparams;
263
264 if (pMech == NULL) {
265 return (CKR_ARGUMENTS_BAD);
266 }
267
268 /*
269 * Special case: Normally, the caller must always provide storage
270 * for the derived key handle at phKey. Two (related) mechanisms
271 * are special, in that multiple keys are instead returned via
272 * pMech->pParameter. In these cases the spec says (see 12.38.4
273 * and 12.39.4) that phKey should be a NULL pointer, as it is not used.
274 */
275 switch (pMech->mechanism) {
276 case CKM_SSL3_KEY_AND_MAC_DERIVE:
277 case CKM_TLS_KEY_AND_MAC_DERIVE:
278 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter;
279
280 if ((keyparams == NULL) || (pMech->ulParameterLen
281 != sizeof (CK_SSL3_KEY_MAT_PARAMS)))
282 return (CKR_ARGUMENTS_BAD);
283
284 ssl_key_mat = keyparams->pReturnedKeyMaterial;
285 if (ssl_key_mat == NULL)
286 return (CKR_ARGUMENTS_BAD);
287
288 ssl_keys = B_TRUE;
289 break;
290
291 case CKM_TLS_PRF:
292 tlsprf = B_TRUE;
293 break;
294
295 default:
296 if (phKey == NULL)
297 return (CKR_ARGUMENTS_BAD);
298 };
299
300 rv = meta_handle2session(hSession, &session);
301 if (rv != CKR_OK)
302 return (rv);
303
304 rv = meta_handle2object(hBaseKey, &basekey1);
305 if (rv != CKR_OK)
306 goto finish;
307
308
309 /*
310 * A few oddball mechanisms pass a 2nd object handle in the parameters.
311 * Here we validate that handle, and create a duplicate copy of the
312 * mechanism and parameters. This is done because the application
313 * does not expect these values to be changing, and could be using the
314 * same data in multiple threads (eg concurrent calls to C_DeriveKey).
315 * We copy the data to make sure there are no MT-Safe problems.
316 */
317 switch (pMech->mechanism) {
318
319 case CKM_ECMQV_DERIVE:
320 /* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */
321
322 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
323 != sizeof (CK_ECDH2_DERIVE_PARAMS))) {
324 rv = CKR_ARGUMENTS_BAD;
325 goto finish;
326 }
327
328 /* Duplicate the mechanism and paramaters */
329 ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter;
330 ecdh_params = *ec_tmpptr;
331 metaMech = *pMech;
332 metaMech.pParameter = &ecdh_params;
333 pMech = &metaMech;
334
335 /* Get the key the application is providing */
336 phBaseKey2 = &ecdh_params.hPrivateData;
337 break;
338
339 case CKM_X9_42_DH_HYBRID_DERIVE:
340 case CKM_X9_42_MQV_DERIVE:
341 /* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */
342
343 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
344 != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) {
345 rv = CKR_ARGUMENTS_BAD;
346 goto finish;
347 }
348
349 /* Duplicate the mechanism and paramaters */
350 x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter;
351 x942_params = *x9_tmpptr;
352 metaMech = *pMech;
353 metaMech.pParameter = &x942_params;
354 pMech = &metaMech;
355
356 /* Get the key the application is providing */
357 phBaseKey2 = &x942_params.hPrivateData;
358 break;
359
360 case CKM_CONCATENATE_BASE_AND_KEY:
361 /* uses a CK_OBJECT_HANDLE as the parameter */
362
363 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
364 != sizeof (CK_OBJECT_HANDLE))) {
365 rv = CKR_ARGUMENTS_BAD;
366 goto finish;
367 }
368
369 /* Duplicate the mechanism and paramaters */
370 metaMech = *pMech;
371 pMech = &metaMech;
372
373 /* Get the key the application is providing */
374 phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter;
375 break;
376
377 default:
378 /* nothing special to do. */
379 break;
380 }
381
382 if (phBaseKey2) {
383 rv = meta_handle2object(*phBaseKey2, &basekey2);
384 if (rv != CKR_OK)
385 goto finish;
386 }
387
388 /*
389 * Allocate meta objects to store the derived key(s). Normally just
390 * a single key is created, but the SSL/TLS mechanisms generate four.
391 */
392 rv = meta_object_alloc(session, &newKey1);
393 if (rv != CKR_OK)
394 goto finish;
395
396 if (ssl_keys) {
397 rv = meta_object_alloc(session, &newKey2);
398 if (rv != CKR_OK)
399 goto finish;
400 rv = meta_object_alloc(session, &newKey3);
401 if (rv != CKR_OK)
402 goto finish;
403 rv = meta_object_alloc(session, &newKey4);
404 if (rv != CKR_OK)
405 goto finish;
406 }
407
408
409 /* Perform the actual key derive operation. */
410 rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2,
411 pTemplate, ulAttributeCount, newKey1, newKey2, newKey3, newKey4);
412 if (rv != CKR_OK)
413 goto finish;
414
415 if (tlsprf) {
416 (void) meta_object_dealloc(session, newKey1, B_TRUE);
417 newKey1 = NULL;
418 /* phKey isn't used (is NULL) for mechanism CKM_TLS_PRF. */
419
420 } else {
421 /* Make derived key(s) active and visible to other threads. */
422 meta_object_activate(newKey1);
423 if (ssl_keys) {
424 meta_object_activate(newKey2);
425 meta_object_activate(newKey3);
426 meta_object_activate(newKey4);
427
428 ssl_key_mat->hClientMacSecret
429 = (CK_OBJECT_HANDLE) newKey1;
430 ssl_key_mat->hServerMacSecret
431 = (CK_OBJECT_HANDLE) newKey2;
432 ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3;
433 ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4;
434 /* phKey isn't used (is NULL) for these SSL/TLS mechs */
435
436 } else {
437 *phKey = (CK_OBJECT_HANDLE) newKey1;
438 }
439 }
440
441 finish:
442 if (rv != CKR_OK) {
443 if (newKey1)
444 (void) meta_object_dealloc(session, newKey1, B_TRUE);
445 if (newKey2)
446 (void) meta_object_dealloc(session, newKey2, B_TRUE);
447 if (newKey3)
448 (void) meta_object_dealloc(session, newKey3, B_TRUE);
449 if (newKey4)
450 (void) meta_object_dealloc(session, newKey4, B_TRUE);
451 }
452
453 if (basekey1)
454 OBJRELEASE(basekey1);
455 if (basekey2)
456 OBJRELEASE(basekey2);
457 REFRELEASE(session);
458
459 return (rv);
460 }
461