17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
590e0e8c4Sizick * Common Development and Distribution License (the "License").
690e0e8c4Sizick * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2200756404SDarren J Moffat * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate * Solaris specific functions to reduce the initialization
277c478bd9Sstevel@tonic-gate * overhead of using PKCS #11
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
337c478bd9Sstevel@tonic-gate #include <assert.h>
347c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
3590e0e8c4Sizick #include <pkcs11Global.h>
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate static CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
387c478bd9Sstevel@tonic-gate static CK_BBOOL falsevalue = FALSE;
397c478bd9Sstevel@tonic-gate static CK_BBOOL truevalue = TRUE;
407c478bd9Sstevel@tonic-gate
411c9bd843Sdinak #define NUM_SECRETKEY_ATTRS 12
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate typedef struct _ATTRTYPE_MECHINFO_MAPPING {
447c478bd9Sstevel@tonic-gate CK_ATTRIBUTE_TYPE attr;
457c478bd9Sstevel@tonic-gate CK_FLAGS flag;
467c478bd9Sstevel@tonic-gate } ATTRTYPE_MECHINFO_MAPPING;
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate /* possible attribute types for creating key */
497c478bd9Sstevel@tonic-gate ATTRTYPE_MECHINFO_MAPPING mapping[] = {
507c478bd9Sstevel@tonic-gate {CKA_ENCRYPT, CKF_ENCRYPT},
517c478bd9Sstevel@tonic-gate {CKA_DECRYPT, CKF_DECRYPT},
527c478bd9Sstevel@tonic-gate {CKA_SIGN, CKF_SIGN},
531c9bd843Sdinak {CKA_VERIFY, CKF_VERIFY},
541c9bd843Sdinak {CKA_WRAP, CKF_WRAP},
551c9bd843Sdinak {CKA_UNWRAP, CKF_UNWRAP}
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate * List of mechanisms that only supports asymmetric key operations
617c478bd9Sstevel@tonic-gate * in PKCS #11 V2.11
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE asymmetric_mechs[] = {
647c478bd9Sstevel@tonic-gate CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_9796, CKM_RSA_X_509,
657c478bd9Sstevel@tonic-gate CKM_RSA_PKCS_OAEP, CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31,
667c478bd9Sstevel@tonic-gate CKM_RSA_PKCS_PSS, CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1,
677c478bd9Sstevel@tonic-gate CKM_DSA_PARAMETER_GEN, CKM_ECDSA_KEY_PAIR_GEN, CKM_EC_KEY_PAIR_GEN,
687c478bd9Sstevel@tonic-gate CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDH1_DERIVE,
697c478bd9Sstevel@tonic-gate CKM_ECDH1_COFACTOR_DERIVE, CKM_ECMQV_DERIVE
707c478bd9Sstevel@tonic-gate };
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate
731c9bd843Sdinak typedef struct _KEY_TYPE_SIZE_MAPPING {
741c9bd843Sdinak CK_KEY_TYPE type;
751c9bd843Sdinak CK_ULONG len;
761c9bd843Sdinak } KEY_TYPE_SIZE_MAPPING;
771c9bd843Sdinak
781c9bd843Sdinak /*
791c9bd843Sdinak * List of secret key types that have fixed sizes and their sizes.
801c9bd843Sdinak * These key types do not allow CKA_VALUE_LEN for key generation.
811c9bd843Sdinak * The sizes are in bytes.
821c9bd843Sdinak *
831c9bd843Sdinak * Discrete-sized keys, such as AES and Twofish, and variable sized
841c9bd843Sdinak * keys, such as Blowfish, are not in this list.
851c9bd843Sdinak */
861c9bd843Sdinak KEY_TYPE_SIZE_MAPPING fixed_size_secrets[] = {
871c9bd843Sdinak {CKK_DES, 8}, {CKK_DES2, 16}, {CKK_DES3, 24}, {CKK_IDEA, 16},
881c9bd843Sdinak {CKK_CDMF, 8}, {CKK_SKIPJACK, 12}, {CKK_BATON, 40}, {CKK_JUNIPER, 40}
891c9bd843Sdinak };
901c9bd843Sdinak
9117e2ff97Sdinak /*
9217e2ff97Sdinak * match_mech is an example of many possible criteria functions.
9317e2ff97Sdinak * It matches the given mech type (in args) with the slot's mech info.
9417e2ff97Sdinak * If no match is found, pkcs11_GetCriteriaSession is asked to return
9517e2ff97Sdinak * CKR_MECHANISM_INVALID.
9617e2ff97Sdinak */
9717e2ff97Sdinak boolean_t
match_mech(CK_SLOT_ID slot_id,void * args,CK_RV * rv)9817e2ff97Sdinak match_mech(CK_SLOT_ID slot_id, void *args, CK_RV *rv)
9917e2ff97Sdinak {
10017e2ff97Sdinak CK_MECHANISM_INFO mech_info;
10117e2ff97Sdinak CK_MECHANISM_TYPE mech = (CK_MECHANISM_TYPE)args;
10217e2ff97Sdinak
10317e2ff97Sdinak *rv = CKR_MECHANISM_INVALID;
10417e2ff97Sdinak return (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK);
10517e2ff97Sdinak }
10617e2ff97Sdinak
10717e2ff97Sdinak /*
10817e2ff97Sdinak * pkcs11_GetCriteriaSession will initialize the framework and do all
10917e2ff97Sdinak * the necessary work of calling C_GetSlotList(), C_GetMechanismInfo()
11017e2ff97Sdinak * C_OpenSession() to create a session that meets all the criteria in
11117e2ff97Sdinak * the given function pointer.
11217e2ff97Sdinak *
11317e2ff97Sdinak * The criteria function must return a boolean value of true or false.
11417e2ff97Sdinak * The arguments to the function are the current slot id, an opaque
11517e2ff97Sdinak * args value that is passed through to the function, and the error
11617e2ff97Sdinak * value pkcs11_GetCriteriaSession should return if no slot id meets the
11717e2ff97Sdinak * criteria.
11817e2ff97Sdinak *
11917e2ff97Sdinak * If the function is called multiple times, it will return a new session
12017e2ff97Sdinak * without reinitializing the framework.
12117e2ff97Sdinak */
12217e2ff97Sdinak CK_RV
pkcs11_GetCriteriaSession(boolean_t (* criteria)(CK_SLOT_ID slot_id,void * args,CK_RV * rv),void * args,CK_SESSION_HANDLE_PTR hSession)12317e2ff97Sdinak pkcs11_GetCriteriaSession(
12417e2ff97Sdinak boolean_t (*criteria)(CK_SLOT_ID slot_id, void *args, CK_RV *rv),
12517e2ff97Sdinak void *args, CK_SESSION_HANDLE_PTR hSession)
12617e2ff97Sdinak {
12717e2ff97Sdinak CK_RV rv;
12817e2ff97Sdinak CK_ULONG slotcount;
12917e2ff97Sdinak CK_SLOT_ID_PTR slot_list;
13017e2ff97Sdinak CK_SLOT_ID slot_id;
13117e2ff97Sdinak CK_ULONG i;
13217e2ff97Sdinak
13317e2ff97Sdinak if (hSession == NULL || criteria == NULL) {
13417e2ff97Sdinak return (CKR_ARGUMENTS_BAD);
13517e2ff97Sdinak }
13617e2ff97Sdinak
13717e2ff97Sdinak /* initialize PKCS #11 */
13817e2ff97Sdinak if (!pkcs11_initialized) {
13917e2ff97Sdinak rv = C_Initialize(NULL);
14017e2ff97Sdinak if ((rv != CKR_OK) &&
14117e2ff97Sdinak (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
14217e2ff97Sdinak return (rv);
14317e2ff97Sdinak }
14417e2ff97Sdinak }
14517e2ff97Sdinak
14617e2ff97Sdinak /* get slot count */
14717e2ff97Sdinak rv = C_GetSlotList(0, NULL, &slotcount);
14817e2ff97Sdinak if (rv != CKR_OK) {
14917e2ff97Sdinak return (rv);
15017e2ff97Sdinak }
15117e2ff97Sdinak
15217e2ff97Sdinak if (slotcount == 0) {
15317e2ff97Sdinak return (CKR_FUNCTION_FAILED);
15417e2ff97Sdinak }
15517e2ff97Sdinak
15617e2ff97Sdinak
15717e2ff97Sdinak /* allocate memory for slot list */
15817e2ff97Sdinak slot_list = malloc(slotcount * sizeof (CK_SLOT_ID));
15917e2ff97Sdinak if (slot_list == NULL) {
16017e2ff97Sdinak return (CKR_HOST_MEMORY);
16117e2ff97Sdinak }
16217e2ff97Sdinak
16317e2ff97Sdinak if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) {
16417e2ff97Sdinak free(slot_list);
16517e2ff97Sdinak return (rv);
16617e2ff97Sdinak }
16717e2ff97Sdinak
16817e2ff97Sdinak /* find slot with matching criteria */
16917e2ff97Sdinak for (i = 0; i < slotcount; i++) {
17017e2ff97Sdinak slot_id = slot_list[i];
17117e2ff97Sdinak if ((*criteria)(slot_id, args, &rv)) {
17217e2ff97Sdinak break;
17317e2ff97Sdinak }
17417e2ff97Sdinak }
17517e2ff97Sdinak
17617e2ff97Sdinak if (i == slotcount) {
17717e2ff97Sdinak /* no matching slot found */
17817e2ff97Sdinak free(slot_list);
17917e2ff97Sdinak return (rv); /* this rv is from the criteria function */
18017e2ff97Sdinak }
18117e2ff97Sdinak
18217e2ff97Sdinak rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL,
18317e2ff97Sdinak NULL, hSession);
18417e2ff97Sdinak
18517e2ff97Sdinak free(slot_list);
18617e2ff97Sdinak return (rv);
18717e2ff97Sdinak }
1881c9bd843Sdinak
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * SUNW_C_GetMechSession will initialize the framework and do all
1917c478bd9Sstevel@tonic-gate * of the neccessary work of calling C_GetSlotList(), C_GetMechanismInfo()
19217e2ff97Sdinak * C_OpenSession() to create a session capable of providing the requested
1937c478bd9Sstevel@tonic-gate * mechanism.
1947c478bd9Sstevel@tonic-gate *
1957c478bd9Sstevel@tonic-gate * If the function is called multiple times, it will return a new session
1967c478bd9Sstevel@tonic-gate * without reinitializing the framework.
1977c478bd9Sstevel@tonic-gate */
1987c478bd9Sstevel@tonic-gate CK_RV
SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,CK_SESSION_HANDLE_PTR hSession)1997c478bd9Sstevel@tonic-gate SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE_PTR hSession)
2007c478bd9Sstevel@tonic-gate {
20117e2ff97Sdinak /*
20217e2ff97Sdinak * All the code in this function can be replaced with one line:
20317e2ff97Sdinak *
20417e2ff97Sdinak * return (pkcs11_GetCriteriaSession(match_mech, (void *)mech,
20517e2ff97Sdinak * hSession));
20617e2ff97Sdinak *
20717e2ff97Sdinak */
2087c478bd9Sstevel@tonic-gate CK_RV rv;
2097c478bd9Sstevel@tonic-gate CK_ULONG slotcount;
2107c478bd9Sstevel@tonic-gate CK_SLOT_ID_PTR slot_list;
2117c478bd9Sstevel@tonic-gate CK_SLOT_ID slot_id;
2127c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO mech_info;
2137c478bd9Sstevel@tonic-gate CK_ULONG i;
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate if (hSession == NULL) {
2167c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /* initialize PKCS #11 */
22090e0e8c4Sizick if (!pkcs11_initialized) {
22190e0e8c4Sizick rv = C_Initialize(NULL);
22290e0e8c4Sizick if ((rv != CKR_OK) &&
22390e0e8c4Sizick (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
22490e0e8c4Sizick return (rv);
22590e0e8c4Sizick }
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate /* get slot count */
2297c478bd9Sstevel@tonic-gate rv = C_GetSlotList(0, NULL, &slotcount);
2307c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
2317c478bd9Sstevel@tonic-gate return (rv);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate if (slotcount == 0) {
2357c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate /* allocate memory for slot list */
2407c478bd9Sstevel@tonic-gate slot_list = malloc(slotcount * sizeof (CK_SLOT_ID));
2417c478bd9Sstevel@tonic-gate if (slot_list == NULL) {
2427c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) {
2467c478bd9Sstevel@tonic-gate free(slot_list);
2477c478bd9Sstevel@tonic-gate return (rv);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate /* find slot with matching mechanism */
2517c478bd9Sstevel@tonic-gate for (i = 0; i < slotcount; i++) {
2527c478bd9Sstevel@tonic-gate slot_id = slot_list[i];
2537c478bd9Sstevel@tonic-gate if (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK) {
2547c478bd9Sstevel@tonic-gate /* found mechanism */
2557c478bd9Sstevel@tonic-gate break;
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate }
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate if (i == slotcount) {
2607c478bd9Sstevel@tonic-gate /* no matching mechanism found */
2617c478bd9Sstevel@tonic-gate free(slot_list);
2627c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL,
2667c478bd9Sstevel@tonic-gate NULL, hSession);
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate free(slot_list);
2697c478bd9Sstevel@tonic-gate return (rv);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /*
2737c478bd9Sstevel@tonic-gate * SUNW_C_KeyToObject creates a secret key object for the given
2747c478bd9Sstevel@tonic-gate * mechanism from the rawkey data.
2757c478bd9Sstevel@tonic-gate */
2767c478bd9Sstevel@tonic-gate CK_RV
SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,CK_MECHANISM_TYPE mech,const void * rawkey,size_t rawkey_len,CK_OBJECT_HANDLE_PTR obj)2777c478bd9Sstevel@tonic-gate SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mech,
2787c478bd9Sstevel@tonic-gate const void *rawkey, size_t rawkey_len, CK_OBJECT_HANDLE_PTR obj)
2797c478bd9Sstevel@tonic-gate {
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate CK_RV rv;
2827c478bd9Sstevel@tonic-gate CK_SESSION_INFO session_info;
2837c478bd9Sstevel@tonic-gate CK_SLOT_ID slot_id;
2847c478bd9Sstevel@tonic-gate CK_MECHANISM_INFO mech_info;
2857c478bd9Sstevel@tonic-gate CK_ULONG i, j;
2867c478bd9Sstevel@tonic-gate CK_KEY_TYPE keytype;
2877c478bd9Sstevel@tonic-gate CK_ULONG num_asym_mechs, num_mapping;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate /* template for creating generic secret key object */
2907c478bd9Sstevel@tonic-gate CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS];
2917c478bd9Sstevel@tonic-gate
292*07eb1aefSToomas Soome if ((hSession == CK_INVALID_HANDLE) || (obj == NULL) ||
2937c478bd9Sstevel@tonic-gate (rawkey == NULL) || (rawkey_len == 0)) {
2947c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /*
2987c478bd9Sstevel@tonic-gate * Check to make sure mechanism type is not for asymmetric key
2997c478bd9Sstevel@tonic-gate * only operations. This function is only applicable to
3007c478bd9Sstevel@tonic-gate * generating secret key.
3017c478bd9Sstevel@tonic-gate */
3027c478bd9Sstevel@tonic-gate num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE);
3037c478bd9Sstevel@tonic-gate for (i = 0; i < num_asym_mechs; i++) {
3047c478bd9Sstevel@tonic-gate if (mech == asymmetric_mechs[i]) {
3057c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate rv = C_GetSessionInfo(hSession, &session_info);
3107c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3111c9bd843Sdinak return (rv);
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate slot_id = session_info.slotID;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate i = 0;
3177c478bd9Sstevel@tonic-gate template[i].type = CKA_CLASS;
3187c478bd9Sstevel@tonic-gate template[i].pValue = &objclass;
3197c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (objclass);
3207c478bd9Sstevel@tonic-gate i++;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate /* get the key type for this mechanism */
3237c478bd9Sstevel@tonic-gate if ((rv = pkcs11_mech2keytype(mech, &keytype)) != CKR_OK) {
3247c478bd9Sstevel@tonic-gate return (rv);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate assert(i < NUM_SECRETKEY_ATTRS);
3287c478bd9Sstevel@tonic-gate template[i].type = CKA_KEY_TYPE;
3297c478bd9Sstevel@tonic-gate template[i].pValue = &keytype;
3307c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (keytype);
3317c478bd9Sstevel@tonic-gate i++;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate rv = C_GetMechanismInfo(slot_id, mech, &mech_info);
3347c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
3351c9bd843Sdinak return (rv);
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate
3381c9bd843Sdinak /* set the attribute type flag on object based on mechanism */
3397c478bd9Sstevel@tonic-gate num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING);
3407c478bd9Sstevel@tonic-gate for (j = 0; j < num_mapping; j++) {
3417c478bd9Sstevel@tonic-gate assert(i < NUM_SECRETKEY_ATTRS);
3427c478bd9Sstevel@tonic-gate template[i].type = mapping[j].attr;
3437c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (falsevalue);
3447c478bd9Sstevel@tonic-gate if (mech_info.flags & ((mapping[j]).flag)) {
3457c478bd9Sstevel@tonic-gate template[i].pValue = &truevalue;
3467c478bd9Sstevel@tonic-gate } else {
3477c478bd9Sstevel@tonic-gate template[i].pValue = &falsevalue;
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate i++;
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate assert(i < NUM_SECRETKEY_ATTRS);
3537c478bd9Sstevel@tonic-gate template[i].type = CKA_TOKEN;
3547c478bd9Sstevel@tonic-gate template[i].pValue = &falsevalue;
3557c478bd9Sstevel@tonic-gate template[i].ulValueLen = sizeof (falsevalue);
3567c478bd9Sstevel@tonic-gate i++;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate assert(i < NUM_SECRETKEY_ATTRS);
3597c478bd9Sstevel@tonic-gate template[i].type = CKA_VALUE;
3607c478bd9Sstevel@tonic-gate template[i].pValue = (CK_VOID_PTR)rawkey;
3617c478bd9Sstevel@tonic-gate template[i].ulValueLen = (CK_ULONG)rawkey_len;
3627c478bd9Sstevel@tonic-gate i++;
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate rv = C_CreateObject(hSession, template, i, obj);
3651c9bd843Sdinak return (rv);
3661c9bd843Sdinak }
3671c9bd843Sdinak
3681c9bd843Sdinak
3691c9bd843Sdinak /*
3701c9bd843Sdinak * pkcs11_PasswdToPBKD2Object will create a secret key from the given string
3711c9bd843Sdinak * (e.g. passphrase) using PKCS#5 Password-Based Key Derivation Function 2
3721c9bd843Sdinak * (PBKD2).
3731c9bd843Sdinak *
3741c9bd843Sdinak * Session must be open. Salt and iterations use defaults.
3751c9bd843Sdinak */
3761c9bd843Sdinak CK_RV
pkcs11_PasswdToPBKD2Object(CK_SESSION_HANDLE hSession,char * passphrase,size_t passphrase_len,void * salt,size_t salt_len,CK_ULONG iterations,CK_KEY_TYPE key_type,CK_ULONG key_len,CK_FLAGS key_flags,CK_OBJECT_HANDLE_PTR obj)3771c9bd843Sdinak pkcs11_PasswdToPBKD2Object(CK_SESSION_HANDLE hSession, char *passphrase,
3781c9bd843Sdinak size_t passphrase_len, void *salt, size_t salt_len, CK_ULONG iterations,
3791c9bd843Sdinak CK_KEY_TYPE key_type, CK_ULONG key_len, CK_FLAGS key_flags,
3801c9bd843Sdinak CK_OBJECT_HANDLE_PTR obj)
3811c9bd843Sdinak {
3821c9bd843Sdinak CK_RV rv;
3831c9bd843Sdinak CK_PKCS5_PBKD2_PARAMS params;
3841c9bd843Sdinak CK_MECHANISM mechanism;
3851c9bd843Sdinak CK_KEY_TYPE asym_key_type;
3861c9bd843Sdinak CK_ULONG i, j, num_asym_mechs, num_fixed_secs, num_mapping;
3871c9bd843Sdinak CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS];
3881c9bd843Sdinak
389*07eb1aefSToomas Soome if (hSession == CK_INVALID_HANDLE || obj == NULL ||
3901c9bd843Sdinak passphrase == NULL || passphrase_len == 0 ||
3911c9bd843Sdinak iterations == 0UL) {
3921c9bd843Sdinak return (CKR_ARGUMENTS_BAD);
3931c9bd843Sdinak }
3941c9bd843Sdinak
3951c9bd843Sdinak /*
3961c9bd843Sdinak * Check to make sure key type is not asymmetric. This function
3971c9bd843Sdinak * is only applicable to generating secret key.
3981c9bd843Sdinak */
3991c9bd843Sdinak num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE);
4001c9bd843Sdinak for (i = 0; i < num_asym_mechs; i++) {
4011c9bd843Sdinak rv = pkcs11_mech2keytype(asymmetric_mechs[i], &asym_key_type);
4021c9bd843Sdinak assert(rv == CKR_OK);
4031c9bd843Sdinak if (key_type == asym_key_type) {
4041c9bd843Sdinak return (CKR_KEY_TYPE_INCONSISTENT);
4051c9bd843Sdinak }
4061c9bd843Sdinak }
4071c9bd843Sdinak
4081c9bd843Sdinak /*
4091c9bd843Sdinak * Key length must either be 0 or the correct size for PBKD of
4101c9bd843Sdinak * fixed-size secret keys. However, underlying key generation
4111c9bd843Sdinak * cannot have CKA_VALUE_LEN set for the key length attribute.
4121c9bd843Sdinak */
4131c9bd843Sdinak num_fixed_secs =
4141c9bd843Sdinak sizeof (fixed_size_secrets) / sizeof (KEY_TYPE_SIZE_MAPPING);
4151c9bd843Sdinak for (i = 0; i < num_fixed_secs; i++) {
4161c9bd843Sdinak if (key_type == fixed_size_secrets[i].type) {
4171c9bd843Sdinak if (key_len == fixed_size_secrets[i].len) {
4181c9bd843Sdinak key_len = 0;
4191c9bd843Sdinak }
4201c9bd843Sdinak if (key_len == 0) {
4211c9bd843Sdinak break;
4221c9bd843Sdinak }
4231c9bd843Sdinak return (CKR_KEY_SIZE_RANGE);
4241c9bd843Sdinak }
4251c9bd843Sdinak }
4261c9bd843Sdinak
4271c9bd843Sdinak if (salt == NULL || salt_len == 0) {
4281c9bd843Sdinak params.saltSource = 0;
4291c9bd843Sdinak params.pSaltSourceData = NULL;
4301c9bd843Sdinak params.ulSaltSourceDataLen = 0;
4311c9bd843Sdinak } else {
4321c9bd843Sdinak params.saltSource = CKZ_SALT_SPECIFIED;
4331c9bd843Sdinak params.pSaltSourceData = salt;
4341c9bd843Sdinak params.ulSaltSourceDataLen = salt_len;
4351c9bd843Sdinak }
4361c9bd843Sdinak params.iterations = iterations;
4371c9bd843Sdinak params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
4381c9bd843Sdinak params.pPrfData = NULL;
4391c9bd843Sdinak params.ulPrfDataLen = 0;
4401c9bd843Sdinak params.pPassword = (CK_UTF8CHAR_PTR)passphrase;
4411c9bd843Sdinak params.ulPasswordLen = (CK_ULONG_PTR)&passphrase_len;
4421c9bd843Sdinak /*
4431c9bd843Sdinak * PKCS#11 spec error, ulPasswordLen should have been pulPasswordLen,
4441c9bd843Sdinak * or its type should have been CK_ULONG instead of CK_ULONG_PTR,
4451c9bd843Sdinak * but it's legacy now
4461c9bd843Sdinak */
4471c9bd843Sdinak
4481c9bd843Sdinak mechanism.mechanism = CKM_PKCS5_PBKD2;
4491c9bd843Sdinak mechanism.pParameter = ¶ms;
4501c9bd843Sdinak mechanism.ulParameterLen = sizeof (params);
4511c9bd843Sdinak
4521c9bd843Sdinak i = 0;
4531c9bd843Sdinak template[i].type = CKA_CLASS;
4541c9bd843Sdinak template[i].pValue = &objclass;
4551c9bd843Sdinak template[i].ulValueLen = sizeof (objclass);
4561c9bd843Sdinak i++;
4571c9bd843Sdinak
4581c9bd843Sdinak assert(i < NUM_SECRETKEY_ATTRS);
4591c9bd843Sdinak template[i].type = CKA_KEY_TYPE;
4601c9bd843Sdinak template[i].pValue = &key_type;
4611c9bd843Sdinak template[i].ulValueLen = sizeof (key_type);
4621c9bd843Sdinak i++;
4631c9bd843Sdinak
4641c9bd843Sdinak assert(i < NUM_SECRETKEY_ATTRS);
4651c9bd843Sdinak template[i].type = CKA_TOKEN;
4661c9bd843Sdinak template[i].pValue = &falsevalue;
4671c9bd843Sdinak template[i].ulValueLen = sizeof (falsevalue);
4681c9bd843Sdinak i++;
4691c9bd843Sdinak
4701c9bd843Sdinak if (key_len != 0) {
4711c9bd843Sdinak assert(i < NUM_SECRETKEY_ATTRS);
4721c9bd843Sdinak template[i].type = CKA_VALUE_LEN;
4731c9bd843Sdinak template[i].pValue = &key_len;
4741c9bd843Sdinak template[i].ulValueLen = sizeof (key_len);
4751c9bd843Sdinak i++;
4761c9bd843Sdinak }
4771c9bd843Sdinak
4781c9bd843Sdinak /*
4791c9bd843Sdinak * C_GenerateKey may not implicitly set capability attributes,
4801c9bd843Sdinak * e.g. CKA_ENCRYPT, CKA_DECRYPT, CKA_WRAP, CKA_UNWRAP, ...
4811c9bd843Sdinak */
4821c9bd843Sdinak num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING);
4831c9bd843Sdinak for (j = 0; j < num_mapping; j++) {
4841c9bd843Sdinak assert(i < NUM_SECRETKEY_ATTRS);
4851c9bd843Sdinak template[i].type = mapping[j].attr;
4861c9bd843Sdinak template[i].pValue = (key_flags & ((mapping[j]).flag)) ?
4871c9bd843Sdinak &truevalue : &falsevalue;
4881c9bd843Sdinak template[i].ulValueLen = sizeof (falsevalue);
4891c9bd843Sdinak i++;
4901c9bd843Sdinak }
4911c9bd843Sdinak
4921c9bd843Sdinak rv = C_GenerateKey(hSession, &mechanism, template, i, obj);
4931c9bd843Sdinak return (rv);
4941c9bd843Sdinak }
4951c9bd843Sdinak
4961c9bd843Sdinak /*
4971c9bd843Sdinak * pkcs11_ObjectToKey gets the rawkey data from a secret key object.
4981c9bd843Sdinak * The caller is responsible to free the allocated rawkey data.
4991c9bd843Sdinak *
5001c9bd843Sdinak * Optionally the object can be destroyed after the value is retrieved.
5011c9bd843Sdinak * As an example, after using pkcs11_PasswdToPBKD2Object() to create a
5021c9bd843Sdinak * secret key object from a passphrase, an app may call pkcs11_ObjectToKey
5031c9bd843Sdinak * to get the rawkey data. The intermediate object may no longer be needed
5041c9bd843Sdinak * and should be destroyed.
5051c9bd843Sdinak */
5061c9bd843Sdinak CK_RV
pkcs11_ObjectToKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE obj,void ** rawkey,size_t * rawkey_len,boolean_t destroy_obj)5071c9bd843Sdinak pkcs11_ObjectToKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
5081c9bd843Sdinak void **rawkey, size_t *rawkey_len, boolean_t destroy_obj)
5091c9bd843Sdinak {
5101c9bd843Sdinak CK_RV rv;
5111c9bd843Sdinak CK_ATTRIBUTE template;
5121c9bd843Sdinak
513*07eb1aefSToomas Soome if (hSession == CK_INVALID_HANDLE)
51400756404SDarren J Moffat return (CKR_SESSION_HANDLE_INVALID);
515*07eb1aefSToomas Soome if (obj == 0)
51600756404SDarren J Moffat return (CKR_OBJECT_HANDLE_INVALID);
51700756404SDarren J Moffat if (rawkey == NULL || rawkey_len == NULL)
5181c9bd843Sdinak return (CKR_ARGUMENTS_BAD);
5191c9bd843Sdinak
5201c9bd843Sdinak template.type = CKA_VALUE;
5211c9bd843Sdinak template.pValue = NULL;
5221c9bd843Sdinak template.ulValueLen = 0;
5231c9bd843Sdinak
5241c9bd843Sdinak /* First get the size of the rawkey */
5251c9bd843Sdinak rv = C_GetAttributeValue(hSession, obj, &template, 1);
5267c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
5277c478bd9Sstevel@tonic-gate return (rv);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate
5301c9bd843Sdinak template.pValue = malloc(template.ulValueLen);
5311c9bd843Sdinak if (template.pValue == NULL) {
5321c9bd843Sdinak return (CKR_HOST_MEMORY);
5331c9bd843Sdinak }
5341c9bd843Sdinak
5351c9bd843Sdinak /* Then get the rawkey data */
5361c9bd843Sdinak rv = C_GetAttributeValue(hSession, obj, &template, 1);
5371c9bd843Sdinak if (rv != CKR_OK) {
5381c9bd843Sdinak free(template.pValue);
5391c9bd843Sdinak return (rv);
5401c9bd843Sdinak }
5411c9bd843Sdinak
5421c9bd843Sdinak if (destroy_obj) {
5431c9bd843Sdinak /*
5441c9bd843Sdinak * Could have asserted rv == CKR_OK, making threaded
5451c9bd843Sdinak * apps that share objects see stars. Here mercy is ok.
5461c9bd843Sdinak */
5471c9bd843Sdinak (void) C_DestroyObject(hSession, obj);
5481c9bd843Sdinak }
5491c9bd843Sdinak
5501c9bd843Sdinak *rawkey = template.pValue;
5511c9bd843Sdinak *rawkey_len = template.ulValueLen;
5527c478bd9Sstevel@tonic-gate
5531c9bd843Sdinak return (CKR_OK);
5541c9bd843Sdinak }
5551c9bd843Sdinak
5561c9bd843Sdinak /*
5571c9bd843Sdinak * pkcs11_PasswdToKey will create PKCS#5 PBKD2 rawkey data from the
5581c9bd843Sdinak * given passphrase. The caller is responsible to free the allocated
5591c9bd843Sdinak * rawkey data.
5601c9bd843Sdinak */
5611c9bd843Sdinak CK_RV
pkcs11_PasswdToKey(CK_SESSION_HANDLE hSession,char * passphrase,size_t passphrase_len,void * salt,size_t salt_len,CK_KEY_TYPE key_type,CK_ULONG key_len,void ** rawkey,size_t * rawkey_len)5621c9bd843Sdinak pkcs11_PasswdToKey(CK_SESSION_HANDLE hSession, char *passphrase,
5631c9bd843Sdinak size_t passphrase_len, void *salt, size_t salt_len, CK_KEY_TYPE key_type,
5641c9bd843Sdinak CK_ULONG key_len, void **rawkey, size_t *rawkey_len)
5651c9bd843Sdinak {
5661c9bd843Sdinak CK_RV rv;
5671c9bd843Sdinak CK_OBJECT_HANDLE obj;
5681c9bd843Sdinak
5691c9bd843Sdinak rv = pkcs11_PasswdToPBKD2Object(hSession, passphrase, passphrase_len,
5701c9bd843Sdinak salt, salt_len, CK_PKCS5_PBKD2_ITERATIONS, key_type, key_len, 0,
5711c9bd843Sdinak &obj);
5721c9bd843Sdinak if (rv != CKR_OK)
5731c9bd843Sdinak return (rv);
5741c9bd843Sdinak rv = pkcs11_ObjectToKey(hSession, obj, rawkey, rawkey_len, B_TRUE);
5757c478bd9Sstevel@tonic-gate return (rv);
5767c478bd9Sstevel@tonic-gate }
577