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 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)kernelUtil.c 1.16 07/09/11 SMI"
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <cryptoutil.h>
32 #include <errno.h>
33 #include <security/cryptoki.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/ioctl.h>
36 #include "kernelGlobal.h"
37 #include "kernelObject.h"
38 #include "kernelSlot.h"
39
40 #define ENCODE_ATTR(type, value, len) { \
41 cur_attr->oa_type = type; \
42 (void) memcpy(ptr, value, len); \
43 cur_attr->oa_value = ptr; \
44 cur_attr->oa_value_len = len; \
45 cur_attr++; \
46 }
47
48 #define CRYPTO_LAST_ERROR (CRYPTO_WEAK_KEY + 1)
49
50 /*
175 (void) pthread_mutex_lock(&mechhash_mutex);
176 for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
177 if (type == cur->type) {
178 /* Some other thread beat us to it. */
179 (void) pthread_mutex_unlock(&mechhash_mutex);
180 free(elem);
181 return (CKR_OK);
182 }
183 }
184 elem->knext = kernel_mechhash[h];
185 kernel_mechhash[h] = elem;
186 (void) pthread_mutex_unlock(&mechhash_mutex);
187
188 return (CKR_OK);
189 }
190
191 CK_RV
192 kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
193 {
194 crypto_get_mechanism_number_t get_number;
195 char *string;
196 CK_RV rv;
197 int r;
198 kmh_elem_t *elem;
199 uint_t h;
200
201 /*
202 * Search for an existing entry. No need to lock since we are
203 * just a reader and we never free the entries in the hash table.
204 */
205 h = MECH_HASH(type);
206 for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
207 if (type == elem->type) {
208 *k_number = elem->kmech;
209 return (CKR_OK);
210 }
211 }
212
213 string = pkcs11_mech2str(type);
214 if (string == NULL)
215 return (CKR_MECHANISM_INVALID);
216
217 get_number.pn_mechanism_string = string;
218 get_number.pn_mechanism_len = strlen(string) + 1;
219
220 while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
221 &get_number)) < 0) {
222 if (errno != EINTR)
223 break;
224 }
225 if (r < 0) {
226 rv = CKR_MECHANISM_INVALID;
227 } else {
228 if (get_number.pn_return_value != CRYPTO_SUCCESS) {
229 rv = crypto2pkcs11_error_number(
230 get_number.pn_return_value);
231 } else {
232 rv = CKR_OK;
233 }
234 }
235
236 if (rv == CKR_OK) {
237 *k_number = get_number.pn_internal_number;
238 /* Add this to the hash table */
239 (void) kmech_hash_insert(type, *k_number);
240 }
241
242 free(string);
243 return (rv);
244 }
245
246
247 /*
248 * Return the value of a secret key object.
249 * This routine allocates memory for the value.
250 * A null pointer is returned on error.
251 */
252 unsigned char *
253 get_symmetric_key_value(kernel_object_t *key_p)
254 {
255 uint8_t *cipherKey;
256
257 switch (key_p->class) {
258
259 case CKO_SECRET_KEY:
260
261 cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
262 if (cipherKey == NULL)
1157
1158 failed_exit:
1159
1160 /* Free the newly created token object wrappers. */
1161 objp = new_tobj_list;
1162 while (objp) {
1163 objp1 = objp->next;
1164 (void) pthread_mutex_destroy(&objp->object_mutex);
1165 free(objp);
1166 objp = objp1;
1167 }
1168
1169 return (rv);
1170 }
1171
1172
1173 /*
1174 * Get the value of the CKA_PRIVATE attribute for the object just returned
1175 * from the HW provider. This function will be called by any function
1176 * that creates a new object, because the CKA_PRIVATE value of an object is
1177 * token sepecific. The CKA_PRIVATE attribute value of the new object will be
1178 * stored in the object structure in the library, which will be used later at
1179 * C_Logout to clean up all private objects.
1180 */
1181 CK_RV
1182 get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1183 CK_BBOOL *is_pri_obj)
1184 {
1185 CK_RV rv = CKR_OK;
1186 crypto_object_get_attribute_value_t obj_ga;
1187 crypto_object_attribute_t obj_attr;
1188 CK_BBOOL pri_value;
1189 int r;
1190
1191 obj_ga.og_session = sp->k_session;
1192 obj_ga.og_handle = oid;
1193 obj_ga.og_count = 1;
1194
1195 obj_attr.oa_type = CKA_PRIVATE;
1196 obj_attr.oa_value = (char *)&pri_value;
1197 obj_attr.oa_value_len = sizeof (CK_BBOOL);
1204 }
1205 if (r < 0) {
1206 rv = CKR_FUNCTION_FAILED;
1207 } else {
1208 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1209 }
1210
1211 if (rv == CKR_OK) {
1212 *is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1213 }
1214
1215 return (rv);
1216 }
1217
1218
1219 CK_RV
1220 get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1221 CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1222 {
1223 crypto_get_provider_mechanism_info_t mechanism_info;
1224 char *string;
1225 CK_FLAGS flags, mi_flags;
1226 CK_RV rv;
1227 int r;
1228
1229 string = pkcs11_mech2str(type);
1230 if (string == NULL)
1231 return (CKR_MECHANISM_INVALID);
1232
1233 (void) strcpy(mechanism_info.mi_mechanism_name, string);
1234 mechanism_info.mi_provider_id = pslot->sl_provider_id;
1235
1236 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1237 &mechanism_info)) < 0) {
1238 if (errno != EINTR)
1239 break;
1240 }
1241 if (r < 0) {
1242 rv = CKR_FUNCTION_FAILED;
1243 } else {
1244 rv = crypto2pkcs11_error_number(
1245 mechanism_info.mi_return_value);
1246 }
1247
1248 if (rv != CKR_OK) {
1249 goto out;
1250 }
1251
1252 /*
1253 * Atomic flags are not part of PKCS#11 so we filter
1254 * them out here.
1255 */
1256 mi_flags = mechanism_info.mi_flags;
1257 mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1258 CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1259 CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1260 CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1261 CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1262 CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1263 CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1264
1265 if (mi_flags == 0) {
1266 rv = CKR_MECHANISM_INVALID;
1267 goto out;
1268 }
1269
1270 if (rv == CKR_OK) {
1271 /* set the value of k_mi_flags first */
1272 *k_mi_flags = mi_flags;
1273
1274 /* convert KEF flags into pkcs11 flags */
1275 flags = CKF_HW;
1276 if (mi_flags & CRYPTO_FG_ENCRYPT)
1277 flags |= CKF_ENCRYPT;
1278 if (mi_flags & CRYPTO_FG_DECRYPT) {
1279 flags |= CKF_DECRYPT;
1280 /*
1281 * Since we'll be emulating C_UnwrapKey() for some
1282 * cases, we can go ahead and claim CKF_UNWRAP
1283 */
1284 flags |= CKF_UNWRAP;
1285 }
1286 if (mi_flags & CRYPTO_FG_DIGEST)
1287 flags |= CKF_DIGEST;
1293 flags |= CKF_VERIFY;
1294 if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1295 flags |= CKF_VERIFY_RECOVER;
1296 if (mi_flags & CRYPTO_FG_GENERATE)
1297 flags |= CKF_GENERATE;
1298 if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1299 flags |= CKF_GENERATE_KEY_PAIR;
1300 if (mi_flags & CRYPTO_FG_WRAP)
1301 flags |= CKF_WRAP;
1302 if (mi_flags & CRYPTO_FG_UNWRAP)
1303 flags |= CKF_UNWRAP;
1304 if (mi_flags & CRYPTO_FG_DERIVE)
1305 flags |= CKF_DERIVE;
1306
1307 pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1308 pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1309 pInfo->flags = flags;
1310
1311 }
1312
1313 out:
1314 free(string);
1315 return (rv);
1316 }
|
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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)kernelUtil.c 1.17 08/06/30 SMI"
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <stdio.h>
32 #include <cryptoutil.h>
33 #include <errno.h>
34 #include <security/cryptoki.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/ioctl.h>
37 #include "kernelGlobal.h"
38 #include "kernelObject.h"
39 #include "kernelSlot.h"
40
41 #define ENCODE_ATTR(type, value, len) { \
42 cur_attr->oa_type = type; \
43 (void) memcpy(ptr, value, len); \
44 cur_attr->oa_value = ptr; \
45 cur_attr->oa_value_len = len; \
46 cur_attr++; \
47 }
48
49 #define CRYPTO_LAST_ERROR (CRYPTO_WEAK_KEY + 1)
50
51 /*
176 (void) pthread_mutex_lock(&mechhash_mutex);
177 for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) {
178 if (type == cur->type) {
179 /* Some other thread beat us to it. */
180 (void) pthread_mutex_unlock(&mechhash_mutex);
181 free(elem);
182 return (CKR_OK);
183 }
184 }
185 elem->knext = kernel_mechhash[h];
186 kernel_mechhash[h] = elem;
187 (void) pthread_mutex_unlock(&mechhash_mutex);
188
189 return (CKR_OK);
190 }
191
192 CK_RV
193 kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number)
194 {
195 crypto_get_mechanism_number_t get_number;
196 const char *string;
197 CK_RV rv;
198 int r;
199 kmh_elem_t *elem;
200 uint_t h;
201 char buf[11]; /* Num chars for representing ulong in ASCII */
202
203 /*
204 * Search for an existing entry. No need to lock since we are
205 * just a reader and we never free the entries in the hash table.
206 */
207 h = MECH_HASH(type);
208 for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) {
209 if (type == elem->type) {
210 *k_number = elem->kmech;
211 return (CKR_OK);
212 }
213 }
214
215 if (type > CKM_VENDOR_DEFINED) {
216 (void) snprintf(buf, sizeof (buf), "%#lx", type);
217 string = buf;
218 } else {
219 string = pkcs11_mech2str(type);
220 }
221
222 if (string == NULL)
223 return (CKR_MECHANISM_INVALID);
224
225 get_number.pn_mechanism_string = (char *)string;
226 get_number.pn_mechanism_len = strlen(string) + 1;
227
228 while ((r = ioctl(kernel_fd, CRYPTO_GET_MECHANISM_NUMBER,
229 &get_number)) < 0) {
230 if (errno != EINTR)
231 break;
232 }
233 if (r < 0) {
234 rv = CKR_MECHANISM_INVALID;
235 } else {
236 if (get_number.pn_return_value != CRYPTO_SUCCESS) {
237 rv = crypto2pkcs11_error_number(
238 get_number.pn_return_value);
239 } else {
240 rv = CKR_OK;
241 }
242 }
243
244 if (rv == CKR_OK) {
245 *k_number = get_number.pn_internal_number;
246 /* Add this to the hash table */
247 (void) kmech_hash_insert(type, *k_number);
248 }
249
250 return (rv);
251 }
252
253
254 /*
255 * Return the value of a secret key object.
256 * This routine allocates memory for the value.
257 * A null pointer is returned on error.
258 */
259 unsigned char *
260 get_symmetric_key_value(kernel_object_t *key_p)
261 {
262 uint8_t *cipherKey;
263
264 switch (key_p->class) {
265
266 case CKO_SECRET_KEY:
267
268 cipherKey = malloc(OBJ_SEC(key_p)->sk_value_len);
269 if (cipherKey == NULL)
1164
1165 failed_exit:
1166
1167 /* Free the newly created token object wrappers. */
1168 objp = new_tobj_list;
1169 while (objp) {
1170 objp1 = objp->next;
1171 (void) pthread_mutex_destroy(&objp->object_mutex);
1172 free(objp);
1173 objp = objp1;
1174 }
1175
1176 return (rv);
1177 }
1178
1179
1180 /*
1181 * Get the value of the CKA_PRIVATE attribute for the object just returned
1182 * from the HW provider. This function will be called by any function
1183 * that creates a new object, because the CKA_PRIVATE value of an object is
1184 * token specific. The CKA_PRIVATE attribute value of the new object will be
1185 * stored in the object structure in the library, which will be used later at
1186 * C_Logout to clean up all private objects.
1187 */
1188 CK_RV
1189 get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1190 CK_BBOOL *is_pri_obj)
1191 {
1192 CK_RV rv = CKR_OK;
1193 crypto_object_get_attribute_value_t obj_ga;
1194 crypto_object_attribute_t obj_attr;
1195 CK_BBOOL pri_value;
1196 int r;
1197
1198 obj_ga.og_session = sp->k_session;
1199 obj_ga.og_handle = oid;
1200 obj_ga.og_count = 1;
1201
1202 obj_attr.oa_type = CKA_PRIVATE;
1203 obj_attr.oa_value = (char *)&pri_value;
1204 obj_attr.oa_value_len = sizeof (CK_BBOOL);
1211 }
1212 if (r < 0) {
1213 rv = CKR_FUNCTION_FAILED;
1214 } else {
1215 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1216 }
1217
1218 if (rv == CKR_OK) {
1219 *is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1220 }
1221
1222 return (rv);
1223 }
1224
1225
1226 CK_RV
1227 get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1228 CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1229 {
1230 crypto_get_provider_mechanism_info_t mechanism_info;
1231 const char *string;
1232 CK_FLAGS flags, mi_flags;
1233 CK_RV rv;
1234 int r;
1235 char buf[11]; /* Num chars for representing ulong in ASCII */
1236
1237 if (type > CKM_VENDOR_DEFINED) {
1238 /* allocate/build a string containing the mechanism number */
1239 (void) snprintf(buf, sizeof (buf), "%#lx", type);
1240 string = buf;
1241 } else {
1242 string = pkcs11_mech2str(type);
1243 }
1244
1245 if (string == NULL)
1246 return (CKR_MECHANISM_INVALID);
1247
1248 (void) strcpy(mechanism_info.mi_mechanism_name, string);
1249 mechanism_info.mi_provider_id = pslot->sl_provider_id;
1250
1251 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1252 &mechanism_info)) < 0) {
1253 if (errno != EINTR)
1254 break;
1255 }
1256 if (r < 0) {
1257 rv = CKR_FUNCTION_FAILED;
1258 } else {
1259 rv = crypto2pkcs11_error_number(
1260 mechanism_info.mi_return_value);
1261 }
1262
1263 if (rv != CKR_OK) {
1264 return (rv);
1265 }
1266
1267 /*
1268 * Atomic flags are not part of PKCS#11 so we filter
1269 * them out here.
1270 */
1271 mi_flags = mechanism_info.mi_flags;
1272 mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1273 CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1274 CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1275 CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1276 CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1277 CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1278 CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1279
1280 if (mi_flags == 0) {
1281 return (CKR_MECHANISM_INVALID);
1282 }
1283
1284 if (rv == CKR_OK) {
1285 /* set the value of k_mi_flags first */
1286 *k_mi_flags = mi_flags;
1287
1288 /* convert KEF flags into pkcs11 flags */
1289 flags = CKF_HW;
1290 if (mi_flags & CRYPTO_FG_ENCRYPT)
1291 flags |= CKF_ENCRYPT;
1292 if (mi_flags & CRYPTO_FG_DECRYPT) {
1293 flags |= CKF_DECRYPT;
1294 /*
1295 * Since we'll be emulating C_UnwrapKey() for some
1296 * cases, we can go ahead and claim CKF_UNWRAP
1297 */
1298 flags |= CKF_UNWRAP;
1299 }
1300 if (mi_flags & CRYPTO_FG_DIGEST)
1301 flags |= CKF_DIGEST;
1307 flags |= CKF_VERIFY;
1308 if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1309 flags |= CKF_VERIFY_RECOVER;
1310 if (mi_flags & CRYPTO_FG_GENERATE)
1311 flags |= CKF_GENERATE;
1312 if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1313 flags |= CKF_GENERATE_KEY_PAIR;
1314 if (mi_flags & CRYPTO_FG_WRAP)
1315 flags |= CKF_WRAP;
1316 if (mi_flags & CRYPTO_FG_UNWRAP)
1317 flags |= CKF_UNWRAP;
1318 if (mi_flags & CRYPTO_FG_DERIVE)
1319 flags |= CKF_DERIVE;
1320
1321 pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1322 pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1323 pInfo->flags = flags;
1324
1325 }
1326
1327 return (rv);
1328 }
|