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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Solaris specific functions to reduce the initialization 30 * overhead of using PKCS #11 31 */ 32 33 #include <stdlib.h> 34 #include <sys/types.h> 35 #include <security/cryptoki.h> 36 #include <assert.h> 37 #include <cryptoutil.h> 38 #include <pkcs11Global.h> 39 40 static CK_OBJECT_CLASS objclass = CKO_SECRET_KEY; 41 static CK_BBOOL falsevalue = FALSE; 42 static CK_BBOOL truevalue = TRUE; 43 44 #define NUM_SECRETKEY_ATTRS 8 45 46 typedef struct _ATTRTYPE_MECHINFO_MAPPING { 47 CK_ATTRIBUTE_TYPE attr; 48 CK_FLAGS flag; 49 } ATTRTYPE_MECHINFO_MAPPING; 50 51 /* possible attribute types for creating key */ 52 ATTRTYPE_MECHINFO_MAPPING mapping[] = { 53 {CKA_ENCRYPT, CKF_ENCRYPT}, 54 {CKA_DECRYPT, CKF_DECRYPT}, 55 {CKA_SIGN, CKF_SIGN}, 56 {CKA_VERIFY, CKF_VERIFY} 57 }; 58 59 60 /* 61 * List of mechanisms that only supports asymmetric key operations 62 * in PKCS #11 V2.11 63 */ 64 CK_MECHANISM_TYPE asymmetric_mechs[] = { 65 CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_9796, CKM_RSA_X_509, 66 CKM_RSA_PKCS_OAEP, CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, 67 CKM_RSA_PKCS_PSS, CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1, 68 CKM_DSA_PARAMETER_GEN, CKM_ECDSA_KEY_PAIR_GEN, CKM_EC_KEY_PAIR_GEN, 69 CKM_ECDSA, CKM_ECDSA_SHA1, CKM_ECDH1_DERIVE, 70 CKM_ECDH1_COFACTOR_DERIVE, CKM_ECMQV_DERIVE 71 }; 72 73 74 /* 75 * SUNW_C_GetMechSession will initialize the framework and do all 76 * of the neccessary work of calling C_GetSlotList(), C_GetMechanismInfo() 77 * C_OpenSession() to provide a session capable of providing the requested 78 * mechanism. 79 * 80 * If the function is called multiple times, it will return a new session 81 * without reinitializing the framework. 82 */ 83 CK_RV 84 SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech, CK_SESSION_HANDLE_PTR hSession) 85 { 86 CK_RV rv; 87 CK_ULONG slotcount; 88 CK_SLOT_ID_PTR slot_list; 89 CK_SLOT_ID slot_id; 90 CK_MECHANISM_INFO mech_info; 91 CK_ULONG i; 92 93 if (hSession == NULL) { 94 return (CKR_ARGUMENTS_BAD); 95 } 96 97 /* initialize PKCS #11 */ 98 if (!pkcs11_initialized) { 99 rv = C_Initialize(NULL); 100 if ((rv != CKR_OK) && 101 (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 102 return (rv); 103 } 104 } 105 106 /* get slot count */ 107 rv = C_GetSlotList(0, NULL, &slotcount); 108 if (rv != CKR_OK) { 109 return (rv); 110 } 111 112 if (slotcount == 0) { 113 return (CKR_FUNCTION_FAILED); 114 } 115 116 117 /* allocate memory for slot list */ 118 slot_list = malloc(slotcount * sizeof (CK_SLOT_ID)); 119 if (slot_list == NULL) { 120 return (CKR_HOST_MEMORY); 121 } 122 123 if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) { 124 free(slot_list); 125 return (rv); 126 } 127 128 /* find slot with matching mechanism */ 129 for (i = 0; i < slotcount; i++) { 130 slot_id = slot_list[i]; 131 if (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK) { 132 /* found mechanism */ 133 break; 134 } 135 } 136 137 if (i == slotcount) { 138 /* no matching mechanism found */ 139 free(slot_list); 140 return (CKR_MECHANISM_INVALID); 141 } 142 143 rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL, 144 NULL, hSession); 145 146 free(slot_list); 147 return (rv); 148 } 149 150 /* 151 * SUNW_C_KeyToObject creates a secret key object for the given 152 * mechanism from the rawkey data. 153 */ 154 CK_RV 155 SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mech, 156 const void *rawkey, size_t rawkey_len, CK_OBJECT_HANDLE_PTR obj) 157 { 158 159 CK_RV rv; 160 CK_SESSION_INFO session_info; 161 CK_SLOT_ID slot_id; 162 CK_MECHANISM_INFO mech_info; 163 CK_ULONG i, j; 164 CK_KEY_TYPE keytype; 165 CK_ULONG num_asym_mechs, num_mapping; 166 167 /* template for creating generic secret key object */ 168 CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS]; 169 170 if ((hSession == NULL) || (obj == NULL) || 171 (rawkey == NULL) || (rawkey_len == 0)) { 172 return (CKR_ARGUMENTS_BAD); 173 } 174 175 /* 176 * Check to make sure mechanism type is not for asymmetric key 177 * only operations. This function is only applicable to 178 * generating secret key. 179 */ 180 num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE); 181 for (i = 0; i < num_asym_mechs; i++) { 182 if (mech == asymmetric_mechs[i]) { 183 return (CKR_MECHANISM_INVALID); 184 } 185 } 186 187 /* set the attribute type flag on object based on mechanism */ 188 rv = C_GetSessionInfo(hSession, &session_info); 189 if (rv != CKR_OK) { 190 goto cleanup; 191 } 192 193 slot_id = session_info.slotID; 194 195 /* create a generic object first */ 196 i = 0; 197 template[i].type = CKA_CLASS; 198 template[i].pValue = &objclass; 199 template[i].ulValueLen = sizeof (objclass); 200 i++; 201 202 /* get the key type for this mechanism */ 203 if ((rv = pkcs11_mech2keytype(mech, &keytype)) != CKR_OK) { 204 return (rv); 205 } 206 207 assert(i < NUM_SECRETKEY_ATTRS); 208 template[i].type = CKA_KEY_TYPE; 209 template[i].pValue = &keytype; 210 template[i].ulValueLen = sizeof (keytype); 211 i++; 212 213 rv = C_GetMechanismInfo(slot_id, mech, &mech_info); 214 if (rv != CKR_OK) { 215 goto cleanup; 216 } 217 218 num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING); 219 for (j = 0; j < num_mapping; j++) { 220 assert(i < NUM_SECRETKEY_ATTRS); 221 template[i].type = mapping[j].attr; 222 template[i].ulValueLen = sizeof (falsevalue); 223 if (mech_info.flags & ((mapping[j]).flag)) { 224 template[i].pValue = &truevalue; 225 } else { 226 template[i].pValue = &falsevalue; 227 } 228 i++; 229 } 230 231 assert(i < NUM_SECRETKEY_ATTRS); 232 template[i].type = CKA_TOKEN; 233 template[i].pValue = &falsevalue; 234 template[i].ulValueLen = sizeof (falsevalue); 235 i++; 236 237 assert(i < NUM_SECRETKEY_ATTRS); 238 template[i].type = CKA_VALUE; 239 template[i].pValue = (CK_VOID_PTR)rawkey; 240 template[i].ulValueLen = (CK_ULONG)rawkey_len; 241 i++; 242 243 rv = C_CreateObject(hSession, template, i, obj); 244 if (rv != CKR_OK) { 245 return (rv); 246 } 247 248 return (rv); 249 250 cleanup: 251 /* This cleanup is only for failure cases */ 252 (void) C_DestroyObject(hSession, *obj); 253 return (rv); 254 } 255