dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / libpkcs11 / common / metaKeys.c
blob55e1c70a36432dc2e085b7f0d6005eaa02ca7818
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Key Management Functions
28 * (as defined in PKCS#11 spec section 11.14)
31 #include "metaGlobal.h"
35 * meta_GenerateKey
38 CK_RV
39 meta_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
40 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
42 CK_RV rv;
43 meta_session_t *session;
44 meta_object_t *key = NULL;
46 if (pMechanism == NULL || phKey == NULL)
47 return (CKR_ARGUMENTS_BAD);
49 rv = meta_handle2session(hSession, &session);
50 if (rv != CKR_OK)
51 return (rv);
54 rv = meta_object_alloc(session, &key);
55 if (rv != CKR_OK)
56 goto finish;
58 rv = meta_generate_keys(session, pMechanism, pTemplate, ulCount, key,
59 NULL, 0, NULL);
60 if (rv != CKR_OK)
61 goto finish;
63 meta_object_activate(key);
65 *phKey = (CK_OBJECT_HANDLE) key;
67 finish:
68 if (rv != CKR_OK) {
69 if (key)
70 (void) meta_object_dealloc(session, key, B_TRUE);
73 REFRELEASE(session);
75 return (rv);
80 * meta_GenerateKeyPair
83 CK_RV
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)
89 CK_RV rv;
90 meta_session_t *session;
91 meta_object_t *key1 = NULL, *key2 = NULL;
93 if (pMechanism == NULL || phPublicKey == NULL || phPrivateKey == NULL)
94 return (CKR_ARGUMENTS_BAD);
96 rv = meta_handle2session(hSession, &session);
97 if (rv != CKR_OK)
98 return (rv);
101 rv = meta_object_alloc(session, &key1);
102 if (rv != CKR_OK)
103 goto finish;
105 rv = meta_object_alloc(session, &key2);
106 if (rv != CKR_OK)
107 goto finish;
109 rv = meta_generate_keys(session, pMechanism,
110 pPublicKeyTemplate, ulPublicKeyAttributeCount, key1,
111 pPrivateKeyTemplate, ulPrivateKeyAttributeCount, key2);
112 if (rv != CKR_OK)
113 goto finish;
115 meta_object_activate(key1);
116 meta_object_activate(key2);
118 *phPublicKey = (CK_OBJECT_HANDLE) key1;
119 *phPrivateKey = (CK_OBJECT_HANDLE) key2;
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);
129 REFRELEASE(session);
131 return (rv);
136 * meta_WrapKey
139 CK_RV
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)
144 CK_RV rv;
145 meta_session_t *session;
146 meta_object_t *wrappingKey, *inputKey;
148 if (pMechanism == NULL || pulWrappedKeyLen == NULL)
149 return (CKR_ARGUMENTS_BAD);
151 rv = meta_handle2session(hSession, &session);
152 if (rv != CKR_OK)
153 return (rv);
155 rv = meta_handle2object(hKey, &inputKey);
156 if (rv != CKR_OK) {
157 REFRELEASE(session);
158 return (rv);
161 rv = meta_handle2object(hWrappingKey, &wrappingKey);
162 if (rv != CKR_OK) {
163 OBJRELEASE(inputKey);
164 REFRELEASE(session);
165 return (rv);
168 rv = meta_wrap_key(session, pMechanism, wrappingKey,
169 inputKey, pWrappedKey, pulWrappedKeyLen);
171 finish:
172 OBJRELEASE(inputKey);
173 OBJRELEASE(wrappingKey);
174 REFRELEASE(session);
176 return (rv);
181 * meta_UnwrapKey
184 CK_RV
185 meta_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
186 CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey,
187 CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate,
188 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
190 CK_RV rv;
191 meta_session_t *session;
192 meta_object_t *unwrappingKey, *outputKey = NULL;
194 if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL)
195 return (CKR_ARGUMENTS_BAD);
197 rv = meta_handle2session(hSession, &session);
198 if (rv != CKR_OK)
199 return (rv);
201 rv = meta_handle2object(hUnwrappingKey, &unwrappingKey);
202 if (rv != CKR_OK) {
203 REFRELEASE(session);
204 return (rv);
207 rv = meta_object_alloc(session, &outputKey);
208 if (rv != CKR_OK)
209 goto finish;
211 (void) get_template_boolean(CKA_TOKEN, pTemplate, ulAttributeCount,
212 &(outputKey->isToken));
214 rv = meta_unwrap_key(session, pMechanism, unwrappingKey,
215 pWrappedKey, ulWrappedKeyLen,
216 pTemplate, ulAttributeCount, outputKey);
217 if (rv != CKR_OK)
218 goto finish;
220 meta_object_activate(outputKey);
222 *phKey = (CK_OBJECT_HANDLE) outputKey;
224 finish:
225 if (rv != CKR_OK) {
226 if (outputKey)
227 (void) meta_object_dealloc(session, outputKey, B_TRUE);
230 OBJRELEASE(unwrappingKey);
231 REFRELEASE(session);
233 return (rv);
238 * meta_DeriveKey
240 * This function is a bit gross because of PKCS#11 kludges that pass extra
241 * object handles in some mechanism parameters. It probably needs to be
242 * broken up into more managable pieces.
244 CK_RV
245 meta_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
246 CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
247 CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
249 CK_RV rv;
250 CK_MECHANISM *pMech = pMechanism;
251 meta_session_t *session;
252 meta_object_t *basekey1 = NULL, *basekey2 = NULL;
253 meta_object_t *newKey1 = NULL, *newKey2 = NULL, *newKey3 = NULL,
254 *newKey4 = NULL;
255 boolean_t ssl_keys = B_FALSE;
256 boolean_t tlsprf = B_FALSE;
258 CK_MECHANISM metaMech;
259 CK_OBJECT_HANDLE *phBaseKey2 = NULL;
260 CK_X9_42_DH2_DERIVE_PARAMS x942_params, *x9_tmpptr;
261 CK_ECDH2_DERIVE_PARAMS ecdh_params, *ec_tmpptr;
262 CK_SSL3_KEY_MAT_OUT *ssl_key_mat;
263 CK_SSL3_KEY_MAT_PARAMS *keyparams;
265 if (pMech == NULL) {
266 return (CKR_ARGUMENTS_BAD);
270 * Special case: Normally, the caller must always provide storage
271 * for the derived key handle at phKey. Two (related) mechanisms
272 * are special, in that multiple keys are instead returned via
273 * pMech->pParameter. In these cases the spec says (see 12.38.4
274 * and 12.39.4) that phKey should be a NULL pointer, as it is not used.
276 switch (pMech->mechanism) {
277 case CKM_SSL3_KEY_AND_MAC_DERIVE:
278 case CKM_TLS_KEY_AND_MAC_DERIVE:
279 keyparams = (CK_SSL3_KEY_MAT_PARAMS*)pMech->pParameter;
281 if ((keyparams == NULL) || (pMech->ulParameterLen
282 != sizeof (CK_SSL3_KEY_MAT_PARAMS)))
283 return (CKR_ARGUMENTS_BAD);
285 ssl_key_mat = keyparams->pReturnedKeyMaterial;
286 if (ssl_key_mat == NULL)
287 return (CKR_ARGUMENTS_BAD);
289 ssl_keys = B_TRUE;
290 break;
292 case CKM_TLS_PRF:
293 tlsprf = B_TRUE;
294 break;
296 default:
297 if (phKey == NULL)
298 return (CKR_ARGUMENTS_BAD);
301 rv = meta_handle2session(hSession, &session);
302 if (rv != CKR_OK)
303 return (rv);
305 rv = meta_handle2object(hBaseKey, &basekey1);
306 if (rv != CKR_OK)
307 goto finish;
311 * A few oddball mechanisms pass a 2nd object handle in the parameters.
312 * Here we validate that handle, and create a duplicate copy of the
313 * mechanism and parameters. This is done because the application
314 * does not expect these values to be changing, and could be using the
315 * same data in multiple threads (eg concurrent calls to C_DeriveKey).
316 * We copy the data to make sure there are no MT-Safe problems.
318 switch (pMech->mechanism) {
320 case CKM_ECMQV_DERIVE:
321 /* uses CK_ECDH2_DERIVE_PARAMS struct as the parameter */
323 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
324 != sizeof (CK_ECDH2_DERIVE_PARAMS))) {
325 rv = CKR_ARGUMENTS_BAD;
326 goto finish;
329 /* Duplicate the mechanism and paramaters */
330 ec_tmpptr = (CK_ECDH2_DERIVE_PARAMS *)pMech->pParameter;
331 ecdh_params = *ec_tmpptr;
332 metaMech = *pMech;
333 metaMech.pParameter = &ecdh_params;
334 pMech = &metaMech;
336 /* Get the key the application is providing */
337 phBaseKey2 = &ecdh_params.hPrivateData;
338 break;
340 case CKM_X9_42_DH_HYBRID_DERIVE:
341 case CKM_X9_42_MQV_DERIVE:
342 /* both use CK_X9_42_DH2_DERIVE_PARAMS as the parameter */
344 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
345 != sizeof (CK_X9_42_DH2_DERIVE_PARAMS))) {
346 rv = CKR_ARGUMENTS_BAD;
347 goto finish;
350 /* Duplicate the mechanism and paramaters */
351 x9_tmpptr = (CK_X9_42_DH2_DERIVE_PARAMS *)pMech->pParameter;
352 x942_params = *x9_tmpptr;
353 metaMech = *pMech;
354 metaMech.pParameter = &x942_params;
355 pMech = &metaMech;
357 /* Get the key the application is providing */
358 phBaseKey2 = &x942_params.hPrivateData;
359 break;
361 case CKM_CONCATENATE_BASE_AND_KEY:
362 /* uses a CK_OBJECT_HANDLE as the parameter */
364 if ((pMech->pParameter == NULL) || (pMech->ulParameterLen
365 != sizeof (CK_OBJECT_HANDLE))) {
366 rv = CKR_ARGUMENTS_BAD;
367 goto finish;
370 /* Duplicate the mechanism and paramaters */
371 metaMech = *pMech;
372 pMech = &metaMech;
374 /* Get the key the application is providing */
375 phBaseKey2 = (CK_OBJECT_HANDLE *) &metaMech.pParameter;
376 break;
378 default:
379 /* nothing special to do. */
380 break;
383 if (phBaseKey2) {
384 rv = meta_handle2object(*phBaseKey2, &basekey2);
385 if (rv != CKR_OK)
386 goto finish;
390 * Allocate meta objects to store the derived key(s). Normally just
391 * a single key is created, but the SSL/TLS mechanisms generate four.
393 rv = meta_object_alloc(session, &newKey1);
394 if (rv != CKR_OK)
395 goto finish;
397 if (ssl_keys) {
398 rv = meta_object_alloc(session, &newKey2);
399 if (rv != CKR_OK)
400 goto finish;
401 rv = meta_object_alloc(session, &newKey3);
402 if (rv != CKR_OK)
403 goto finish;
404 rv = meta_object_alloc(session, &newKey4);
405 if (rv != CKR_OK)
406 goto finish;
410 /* Perform the actual key derive operation. */
411 rv = meta_derive_key(session, pMech, basekey1, basekey2, phBaseKey2,
412 pTemplate, ulAttributeCount, newKey1, newKey2, newKey3, newKey4);
413 if (rv != CKR_OK)
414 goto finish;
416 if (tlsprf) {
417 (void) meta_object_dealloc(session, newKey1, B_TRUE);
418 newKey1 = NULL;
419 /* phKey isn't used (is NULL) for mechanism CKM_TLS_PRF. */
421 } else {
422 /* Make derived key(s) active and visible to other threads. */
423 meta_object_activate(newKey1);
424 if (ssl_keys) {
425 meta_object_activate(newKey2);
426 meta_object_activate(newKey3);
427 meta_object_activate(newKey4);
429 ssl_key_mat->hClientMacSecret
430 = (CK_OBJECT_HANDLE) newKey1;
431 ssl_key_mat->hServerMacSecret
432 = (CK_OBJECT_HANDLE) newKey2;
433 ssl_key_mat->hClientKey = (CK_OBJECT_HANDLE) newKey3;
434 ssl_key_mat->hServerKey = (CK_OBJECT_HANDLE) newKey4;
435 /* phKey isn't used (is NULL) for these SSL/TLS mechs */
437 } else {
438 *phKey = (CK_OBJECT_HANDLE) newKey1;
442 finish:
443 if (rv != CKR_OK) {
444 if (newKey1)
445 (void) meta_object_dealloc(session, newKey1, B_TRUE);
446 if (newKey2)
447 (void) meta_object_dealloc(session, newKey2, B_TRUE);
448 if (newKey3)
449 (void) meta_object_dealloc(session, newKey3, B_TRUE);
450 if (newKey4)
451 (void) meta_object_dealloc(session, newKey4, B_TRUE);
454 if (basekey1)
455 OBJRELEASE(basekey1);
456 if (basekey2)
457 OBJRELEASE(basekey2);
458 REFRELEASE(session);
460 return (rv);