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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Solaris specific functions to reduce the initialization 31 * overhead of using PKCS #11 32 */ 33 34 #include <stdlib.h> 35 #include <sys/types.h> 36 #include <security/cryptoki.h> 37 #include <assert.h> 38 #include <cryptoutil.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 rv = C_Initialize(NULL); 99 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 100 return (rv); 101 } 102 103 /* get slot count */ 104 rv = C_GetSlotList(0, NULL, &slotcount); 105 if (rv != CKR_OK) { 106 return (rv); 107 } 108 109 if (slotcount == 0) { 110 return (CKR_FUNCTION_FAILED); 111 } 112 113 114 /* allocate memory for slot list */ 115 slot_list = malloc(slotcount * sizeof (CK_SLOT_ID)); 116 if (slot_list == NULL) { 117 return (CKR_HOST_MEMORY); 118 } 119 120 if ((rv = C_GetSlotList(0, slot_list, &slotcount)) != CKR_OK) { 121 free(slot_list); 122 return (rv); 123 } 124 125 /* find slot with matching mechanism */ 126 for (i = 0; i < slotcount; i++) { 127 slot_id = slot_list[i]; 128 if (C_GetMechanismInfo(slot_id, mech, &mech_info) == CKR_OK) { 129 /* found mechanism */ 130 break; 131 } 132 } 133 134 if (i == slotcount) { 135 /* no matching mechanism found */ 136 free(slot_list); 137 return (CKR_MECHANISM_INVALID); 138 } 139 140 rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION, NULL, 141 NULL, hSession); 142 143 free(slot_list); 144 return (rv); 145 } 146 147 /* 148 * SUNW_C_KeyToObject creates a secret key object for the given 149 * mechanism from the rawkey data. 150 */ 151 CK_RV 152 SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mech, 153 const void *rawkey, size_t rawkey_len, CK_OBJECT_HANDLE_PTR obj) 154 { 155 156 CK_RV rv; 157 CK_SESSION_INFO session_info; 158 CK_SLOT_ID slot_id; 159 CK_MECHANISM_INFO mech_info; 160 CK_ULONG i, j; 161 CK_KEY_TYPE keytype; 162 CK_ULONG num_asym_mechs, num_mapping; 163 164 /* template for creating generic secret key object */ 165 CK_ATTRIBUTE template[NUM_SECRETKEY_ATTRS]; 166 167 if ((hSession == NULL) || (obj == NULL) || 168 (rawkey == NULL) || (rawkey_len == 0)) { 169 return (CKR_ARGUMENTS_BAD); 170 } 171 172 /* 173 * Check to make sure mechanism type is not for asymmetric key 174 * only operations. This function is only applicable to 175 * generating secret key. 176 */ 177 num_asym_mechs = sizeof (asymmetric_mechs) / sizeof (CK_MECHANISM_TYPE); 178 for (i = 0; i < num_asym_mechs; i++) { 179 if (mech == asymmetric_mechs[i]) { 180 return (CKR_MECHANISM_INVALID); 181 } 182 } 183 184 /* set the attribute type flag on object based on mechanism */ 185 rv = C_GetSessionInfo(hSession, &session_info); 186 if (rv != CKR_OK) { 187 goto cleanup; 188 } 189 190 slot_id = session_info.slotID; 191 192 /* create a generic object first */ 193 i = 0; 194 template[i].type = CKA_CLASS; 195 template[i].pValue = &objclass; 196 template[i].ulValueLen = sizeof (objclass); 197 i++; 198 199 /* get the key type for this mechanism */ 200 if ((rv = pkcs11_mech2keytype(mech, &keytype)) != CKR_OK) { 201 return (rv); 202 } 203 204 assert(i < NUM_SECRETKEY_ATTRS); 205 template[i].type = CKA_KEY_TYPE; 206 template[i].pValue = &keytype; 207 template[i].ulValueLen = sizeof (keytype); 208 i++; 209 210 rv = C_GetMechanismInfo(slot_id, mech, &mech_info); 211 if (rv != CKR_OK) { 212 goto cleanup; 213 } 214 215 num_mapping = sizeof (mapping) / sizeof (ATTRTYPE_MECHINFO_MAPPING); 216 for (j = 0; j < num_mapping; j++) { 217 assert(i < NUM_SECRETKEY_ATTRS); 218 template[i].type = mapping[j].attr; 219 template[i].ulValueLen = sizeof (falsevalue); 220 if (mech_info.flags & ((mapping[j]).flag)) { 221 template[i].pValue = &truevalue; 222 } else { 223 template[i].pValue = &falsevalue; 224 } 225 i++; 226 } 227 228 assert(i < NUM_SECRETKEY_ATTRS); 229 template[i].type = CKA_TOKEN; 230 template[i].pValue = &falsevalue; 231 template[i].ulValueLen = sizeof (falsevalue); 232 i++; 233 234 assert(i < NUM_SECRETKEY_ATTRS); 235 template[i].type = CKA_VALUE; 236 template[i].pValue = (CK_VOID_PTR)rawkey; 237 template[i].ulValueLen = (CK_ULONG)rawkey_len; 238 i++; 239 240 rv = C_CreateObject(hSession, template, i, obj); 241 if (rv != CKR_OK) { 242 return (rv); 243 } 244 245 return (rv); 246 247 cleanup: 248 /* This cleanup is only for failure cases */ 249 (void) C_DestroyObject(hSession, *obj); 250 return (rv); 251 } 252