Print this page
5031131 perf: pkcs11_kernel can benefit from a more efficient pkcs11_mech2str()


   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 }