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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #include <stdlib.h>
  26 #include <string.h>
  27 #include <strings.h>
  28 #include <stdio.h>
  29 #include <cryptoutil.h>
  30 #include <errno.h>
  31 #include <security/cryptoki.h>
  32 #include <sys/crypto/common.h>
  33 #include <sys/crypto/ioctl.h>
  34 #include "kernelGlobal.h"
  35 #include "kernelObject.h"
  36 #include "kernelSlot.h"
  37 
  38 #define ENCODE_ATTR(type, value, len) {         \
  39         cur_attr->oa_type = type;            \
  40         (void) memcpy(ptr, value, len);         \
  41         cur_attr->oa_value = ptr;            \
  42         cur_attr->oa_value_len = len;                \
  43         cur_attr++;                             \
  44 }
  45 
  46 /*
  47  * In order to fit everything on one line, the 'CRYPTO_' prefix
  48  * has been dropped from the KCF #defines, e.g.
  49  * CRYPTO_SUCCESS becomes SUCCESS.
  50  */
  51 
  52 static CK_RV error_number_table[CRYPTO_LAST_ERROR+1] = {
  53 CKR_OK,                                 /* SUCCESS */
  54 CKR_CANCEL,                             /* CANCEL */
  55 CKR_HOST_MEMORY,                        /* HOST_MEMORY */
  56 CKR_GENERAL_ERROR,                      /* GENERAL_ERROR */
  57 CKR_FUNCTION_FAILED,                    /* FAILED */
  58 CKR_ARGUMENTS_BAD,                      /* ARGUMENTS_BAD */
  59 CKR_ATTRIBUTE_READ_ONLY,                /* ATTRIBUTE_READ_ONLY */
  60 CKR_ATTRIBUTE_SENSITIVE,                /* ATTRIBUTE_SENSITIVE */
  61 CKR_ATTRIBUTE_TYPE_INVALID,             /* ATTRIBUTE_TYPE_INVALID */
  62 CKR_ATTRIBUTE_VALUE_INVALID,            /* ATTRIBUTE_VALUE_INVALID */
  63 CKR_FUNCTION_FAILED,                    /* CANCELED */
  64 CKR_DATA_INVALID,                       /* DATA_INVALID */
  65 CKR_DATA_LEN_RANGE,                     /* DATA_LEN_RANGE */
  66 CKR_DEVICE_ERROR,                       /* DEVICE_ERROR */
  67 CKR_DEVICE_MEMORY,                      /* DEVICE_MEMORY */
  68 CKR_DEVICE_REMOVED,                     /* DEVICE_REMOVED */
  69 CKR_ENCRYPTED_DATA_INVALID,             /* ENCRYPTED_DATA_INVALID */
  70 CKR_ENCRYPTED_DATA_LEN_RANGE,           /* ENCRYPTED_DATA_LEN_RANGE */
  71 CKR_KEY_HANDLE_INVALID,                 /* KEY_HANDLE_INVALID */
  72 CKR_KEY_SIZE_RANGE,                     /* KEY_SIZE_RANGE */
  73 CKR_KEY_TYPE_INCONSISTENT,              /* KEY_TYPE_INCONSISTENT */
  74 CKR_KEY_NOT_NEEDED,                     /* KEY_NOT_NEEDED */
  75 CKR_KEY_CHANGED,                        /* KEY_CHANGED */
  76 CKR_KEY_NEEDED,                         /* KEY_NEEDED */
  77 CKR_KEY_INDIGESTIBLE,                   /* KEY_INDIGESTIBLE */
  78 CKR_KEY_FUNCTION_NOT_PERMITTED,         /* KEY_FUNCTION_NOT_PERMITTED */
  79 CKR_KEY_NOT_WRAPPABLE,                  /* KEY_NOT_WRAPPABLE */
  80 CKR_KEY_UNEXTRACTABLE,                  /* KEY_UNEXTRACTABLE */
  81 CKR_MECHANISM_INVALID,                  /* MECHANISM_INVALID */
  82 CKR_MECHANISM_PARAM_INVALID,            /* MECHANISM_PARAM_INVALID */
  83 CKR_OBJECT_HANDLE_INVALID,              /* OBJECT_HANDLE_INVALID */
  84 CKR_OPERATION_ACTIVE,                   /* OPERATION_ACTIVE */
  85 CKR_OPERATION_NOT_INITIALIZED,          /* OPERATION_NOT_INITIALIZED */
  86 CKR_PIN_INCORRECT,                      /* PIN_INCORRECT */
  87 CKR_PIN_INVALID,                        /* PIN_INVALID */
  88 CKR_PIN_LEN_RANGE,                      /* PIN_LEN_RANGE */
  89 CKR_PIN_EXPIRED,                        /* PIN_EXPIRED */
  90 CKR_PIN_LOCKED,                         /* PIN_LOCKED */
  91 CKR_SESSION_CLOSED,                     /* SESSION_CLOSED */
  92 CKR_SESSION_COUNT,                      /* SESSION_COUNT */
  93 CKR_SESSION_HANDLE_INVALID,             /* SESSION_HANDLE_INVALID */
  94 CKR_SESSION_READ_ONLY,                  /* SESSION_READ_ONLY */
  95 CKR_SESSION_EXISTS,                     /* SESSION_EXISTS */
  96 CKR_SESSION_READ_ONLY_EXISTS,           /* SESSION_READ_ONLY_EXISTS */
  97 CKR_SESSION_READ_WRITE_SO_EXISTS,       /* SESSION_READ_WRITE_SO_EXISTS */
  98 CKR_SIGNATURE_INVALID,                  /* SIGNATURE_INVALID */
  99 CKR_SIGNATURE_LEN_RANGE,                /* SIGNATURE_LEN_RANGE */
 100 CKR_TEMPLATE_INCOMPLETE,                /* TEMPLATE_INCOMPLETE */
 101 CKR_TEMPLATE_INCONSISTENT,              /* TEMPLATE_INCONSISTENT */
 102 CKR_UNWRAPPING_KEY_HANDLE_INVALID,      /* UNWRAPPING_KEY_HANDLE_INVALID */
 103 CKR_UNWRAPPING_KEY_SIZE_RANGE,          /* UNWRAPPING_KEY_SIZE_RANGE */
 104 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,   /* UNWRAPPING_KEY_TYPE_INCONSISTENT */
 105 CKR_USER_ALREADY_LOGGED_IN,             /* USER_ALREADY_LOGGED_IN */
 106 CKR_USER_NOT_LOGGED_IN,                 /* USER_NOT_LOGGED_IN */
 107 CKR_USER_PIN_NOT_INITIALIZED,           /* USER_PIN_NOT_INITIALIZED */
 108 CKR_USER_TYPE_INVALID,                  /* USER_TYPE_INVALID */
 109 CKR_USER_ANOTHER_ALREADY_LOGGED_IN,     /* USER_ANOTHER_ALREADY_LOGGED_IN */
 110 CKR_USER_TOO_MANY_TYPES,                /* USER_TOO_MANY_TYPES */
 111 CKR_WRAPPED_KEY_INVALID,                /* WRAPPED_KEY_INVALID */
 112 CKR_WRAPPED_KEY_LEN_RANGE,              /* WRAPPED_KEY_LEN_RANGE */
 113 CKR_WRAPPING_KEY_HANDLE_INVALID,        /* WRAPPING_KEY_HANDLE_INVALID */
 114 CKR_WRAPPING_KEY_SIZE_RANGE,            /* WRAPPING_KEY_SIZE_RANGE */
 115 CKR_WRAPPING_KEY_TYPE_INCONSISTENT,     /* WRAPPING_KEY_TYPE_INCONSISTENT */
 116 CKR_RANDOM_SEED_NOT_SUPPORTED,          /* RANDOM_SEED_NOT_SUPPORTED */
 117 CKR_RANDOM_NO_RNG,                      /* RANDOM_NO_RNG */
 118 CKR_DOMAIN_PARAMS_INVALID,              /* DOMAIN_PARAMS_INVALID */
 119 CKR_BUFFER_TOO_SMALL,                   /* BUFFER_TOO_SMALL */
 120 CKR_INFORMATION_SENSITIVE,              /* INFORMATION_SENSITIVE */
 121 CKR_FUNCTION_NOT_SUPPORTED,             /* NOT_SUPPORTED */
 122 CKR_GENERAL_ERROR,                      /* QUEUED */
 123 CKR_GENERAL_ERROR,                      /* BUFFER_TOO_BIG */
 124 CKR_OPERATION_NOT_INITIALIZED,          /* INVALID_CONTEXT */
 125 CKR_GENERAL_ERROR,                      /* INVALID_MAC */
 126 CKR_GENERAL_ERROR,                      /* MECH_NOT_SUPPORTED */
 127 CKR_GENERAL_ERROR,                      /* INCONSISTENT_ATTRIBUTE */
 128 CKR_GENERAL_ERROR,                      /* NO_PERMISSION */
 129 CKR_SLOT_ID_INVALID,                    /* INVALID_PROVIDER_ID */
 130 CKR_GENERAL_ERROR,                      /* VERSION_MISMATCH */
 131 CKR_GENERAL_ERROR,                      /* BUSY */
 132 CKR_GENERAL_ERROR,                      /* UNKNOWN_PROVIDER */
 133 CKR_GENERAL_ERROR,                      /* MODVERIFICATION_FAILED */
 134 CKR_GENERAL_ERROR,                      /* OLD_CTX_TEMPLATE */
 135 CKR_GENERAL_ERROR,                      /* WEAK_KEY */
 136 CKR_GENERAL_ERROR                       /* FIPS140_ERROR */
 137 };
 138 
 139 #if CRYPTO_LAST_ERROR != CRYPTO_FIPS140_ERROR
 140 #error "Crypto to PKCS11 error mapping table needs to be updated!"
 141 #endif
 142 
 143 /*
 144  * Map KCF error codes into PKCS11 error codes.
 145  */
 146 CK_RV
 147 crypto2pkcs11_error_number(uint_t n)
 148 {
 149         if (n >= sizeof (error_number_table) / sizeof (error_number_table[0]))
 150                 return (CKR_GENERAL_ERROR);
 151 
 152         return (error_number_table[n]);
 153 }
 154 
 155 #define MECH_HASH(type) (((uintptr_t)type) % KMECH_HASHTABLE_SIZE)
 156 /*
 157  * Serialize writes to the hash table. We don't need a per bucket lock as
 158  * there are only a few writes and we don't need the lock for reads.
 159  */
 160 pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER;
 161 
 162 static CK_RV
 163 kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech)
 164 {
 165         uint_t h;
 166         kmh_elem_t *elem, *cur;
 167 
 168         elem = malloc(sizeof (kmh_elem_t));
 169         if (elem == NULL)
 170                 return (CKR_HOST_MEMORY);
 171 
 172         h = MECH_HASH(type);
 173         elem->type = type;
 174         elem->kmech = kmech;
 175 
 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)
 270                         return (NULL);
 271 
 272                 (void) memcpy(cipherKey, OBJ_SEC(key_p)->sk_value,
 273                     OBJ_SEC(key_p)->sk_value_len);
 274 
 275                 return (cipherKey);
 276 
 277         default:
 278                 return (NULL);
 279         }
 280 }
 281 
 282 /*
 283  * Convert a RSA private key object into a crypto_key structure.
 284  * Memory is allocated for each attribute stored in the crypto_key
 285  * structure.  Memory for the crypto_key structure is not
 286  * allocated.  Attributes can be freed by free_key_attributes().
 287  */
 288 CK_RV
 289 get_rsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
 290 {
 291         biginteger_t *big;
 292         crypto_object_attribute_t *attrs, *cur_attr;
 293         char *ptr;
 294         CK_RV rv;
 295 
 296         (void) pthread_mutex_lock(&object_p->object_mutex);
 297         if (object_p->key_type != CKK_RSA ||
 298             object_p->class != CKO_PRIVATE_KEY) {
 299                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 300                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 301         }
 302 
 303         attrs = calloc(1,
 304             RSA_PRI_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 305         if (attrs == NULL) {
 306                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 307                 return (CKR_HOST_MEMORY);
 308         }
 309 
 310         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 311         key->ck_attrs = attrs;
 312         cur_attr = attrs;
 313 
 314         /*
 315          * Allocate memory for each key attribute and set up the value
 316          * value length.
 317          */
 318         key->ck_count = 0;
 319 
 320         /* CKA_MODULUS is required. */
 321         big = OBJ_PRI_RSA_MOD(object_p);
 322         if (big->big_value == NULL) {
 323                 rv = CKR_ATTRIBUTE_TYPE_INVALID;
 324                 goto fail_cleanup;
 325         } else {
 326                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 327                         rv = CKR_HOST_MEMORY;
 328                         goto fail_cleanup;
 329                 }
 330                 ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
 331                 key->ck_count++;
 332         }
 333 
 334         /* CKA_PRIVATE_EXPONENT is required. */
 335         big = OBJ_PRI_RSA_PRIEXPO(object_p);
 336         if (big->big_value == NULL) {
 337                 rv = CKR_ATTRIBUTE_TYPE_INVALID;
 338                 goto fail_cleanup;
 339         } else {
 340                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 341                         rv = CKR_HOST_MEMORY;
 342                         goto fail_cleanup;
 343                 }
 344                 ENCODE_ATTR(CKA_PRIVATE_EXPONENT, big->big_value,
 345                     big->big_value_len);
 346                 key->ck_count++;
 347         }
 348 
 349         /* CKA_PRIME_1 is optional. */
 350         big = OBJ_PRI_RSA_PRIME1(object_p);
 351         if (big->big_value != NULL) {
 352                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 353                         rv = CKR_HOST_MEMORY;
 354                         goto fail_cleanup;
 355                 }
 356                 ENCODE_ATTR(CKA_PRIME_1, big->big_value, big->big_value_len);
 357                 key->ck_count++;
 358         }
 359 
 360         /* CKA_PRIME_2 is optional. */
 361         big = OBJ_PRI_RSA_PRIME2(object_p);
 362         if (big->big_value != NULL) {
 363                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 364                         rv = CKR_HOST_MEMORY;
 365                         goto fail_cleanup;
 366                 }
 367                 ENCODE_ATTR(CKA_PRIME_2, big->big_value, big->big_value_len);
 368                 key->ck_count++;
 369         }
 370 
 371         /* CKA_EXPONENT_1 is optional. */
 372         big = OBJ_PRI_RSA_EXPO1(object_p);
 373         if (big->big_value != NULL) {
 374                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 375                         rv = CKR_HOST_MEMORY;
 376                         goto fail_cleanup;
 377                 }
 378                 ENCODE_ATTR(CKA_EXPONENT_1, big->big_value,
 379                     big->big_value_len);
 380                 key->ck_count++;
 381         }
 382 
 383         /* CKA_EXPONENT_2 is optional. */
 384         big = OBJ_PRI_RSA_EXPO2(object_p);
 385         if (big->big_value != NULL) {
 386                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 387                         rv = CKR_HOST_MEMORY;
 388                         goto fail_cleanup;
 389                 }
 390                 ENCODE_ATTR(CKA_EXPONENT_2, big->big_value,
 391                     big->big_value_len);
 392                 key->ck_count++;
 393         }
 394 
 395         /* CKA_COEFFICIENT is optional. */
 396         big = OBJ_PRI_RSA_COEF(object_p);
 397         if (big->big_value != NULL) {
 398                 if ((ptr = malloc(big->big_value_len)) == NULL) {
 399                         rv = CKR_HOST_MEMORY;
 400                         goto fail_cleanup;
 401                 }
 402                 ENCODE_ATTR(CKA_COEFFICIENT, big->big_value,
 403                     big->big_value_len);
 404                 key->ck_count++;
 405         }
 406 
 407         (void) pthread_mutex_unlock(&object_p->object_mutex);
 408         return (CKR_OK);
 409 
 410 fail_cleanup:
 411         (void) pthread_mutex_unlock(&object_p->object_mutex);
 412         free_key_attributes(key);
 413         return (rv);
 414 }
 415 
 416 /*
 417  * Convert a RSA public key object into a crypto_key structure.
 418  * Memory is allocated for each attribute stored in the crypto_key
 419  * structure.  Memory for the crypto_key structure is not
 420  * allocated.  Attributes can be freed by free_key_attributes().
 421  */
 422 CK_RV
 423 get_rsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
 424 {
 425         biginteger_t *big;
 426         crypto_object_attribute_t *attrs, *cur_attr;
 427         char *ptr;
 428 
 429         (void) pthread_mutex_lock(&object_p->object_mutex);
 430         if (object_p->key_type != CKK_RSA ||
 431             object_p->class != CKO_PUBLIC_KEY) {
 432                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 433                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 434         }
 435 
 436         attrs = calloc(1,
 437             RSA_PUB_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 438         if (attrs == NULL) {
 439                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 440                 return (CKR_HOST_MEMORY);
 441         }
 442 
 443         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 444         key->ck_count = RSA_PUB_ATTR_COUNT;
 445         key->ck_attrs = attrs;
 446 
 447         cur_attr = attrs;
 448         big = OBJ_PUB_RSA_PUBEXPO(object_p);
 449         if ((ptr = malloc(big->big_value_len)) == NULL)
 450                 goto mem_failure;
 451         ENCODE_ATTR(CKA_PUBLIC_EXPONENT, big->big_value, big->big_value_len);
 452 
 453         big = OBJ_PUB_RSA_MOD(object_p);
 454         if ((ptr = malloc(big->big_value_len)) == NULL)
 455                 goto mem_failure;
 456         ENCODE_ATTR(CKA_MODULUS, big->big_value, big->big_value_len);
 457 
 458         if ((ptr = malloc(sizeof (CK_ULONG))) == NULL)
 459                 goto mem_failure;
 460         ENCODE_ATTR(CKA_MODULUS_BITS, &OBJ_PUB_RSA_MOD_BITS(object_p),
 461             sizeof (CK_ULONG));
 462 
 463         (void) pthread_mutex_unlock(&object_p->object_mutex);
 464         return (CKR_OK);
 465 
 466 mem_failure:
 467         (void) pthread_mutex_unlock(&object_p->object_mutex);
 468         free_key_attributes(key);
 469         return (CKR_HOST_MEMORY);
 470 }
 471 
 472 /*
 473  * Free attribute storage in a crypto_key structure.
 474  */
 475 void
 476 free_key_attributes(crypto_key_t *key)
 477 {
 478         int i;
 479 
 480         if (key->ck_format == CRYPTO_KEY_ATTR_LIST &&
 481             (key->ck_count > 0) && key->ck_attrs != NULL) {
 482                 for (i = 0; i < key->ck_count; i++) {
 483                         if (key->ck_attrs[i].oa_value != NULL) {
 484                                 bzero(key->ck_attrs[i].oa_value,
 485                                     key->ck_attrs[i].oa_value_len);
 486                                 free(key->ck_attrs[i].oa_value);
 487                         }
 488                 }
 489                 free(key->ck_attrs);
 490         }
 491 }
 492 
 493 
 494 /*
 495  * Convert a DSA private key object into a crypto_key structure.
 496  * Memory is allocated for each attribute stored in the crypto_key
 497  * structure.  Memory for the crypto_key structure is not
 498  * allocated.  Attributes can be freed by free_dsa_key_attributes().
 499  */
 500 CK_RV
 501 get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
 502 {
 503         biginteger_t *big;
 504         crypto_object_attribute_t *attrs, *cur_attr;
 505         char *ptr;
 506 
 507         (void) pthread_mutex_lock(&object_p->object_mutex);
 508         if (object_p->key_type != CKK_DSA ||
 509             object_p->class != CKO_PRIVATE_KEY) {
 510                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 511                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 512         }
 513 
 514         attrs = calloc(1,
 515             DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 516         if (attrs == NULL) {
 517                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 518                 return (CKR_HOST_MEMORY);
 519         }
 520 
 521         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 522         key->ck_count = DSA_ATTR_COUNT;
 523         key->ck_attrs = attrs;
 524 
 525         cur_attr = attrs;
 526         big = OBJ_PRI_DSA_PRIME(object_p);
 527         if ((ptr = malloc(big->big_value_len)) == NULL)
 528                 goto mem_failure;
 529         ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
 530 
 531         big = OBJ_PRI_DSA_SUBPRIME(object_p);
 532         if ((ptr = malloc(big->big_value_len)) == NULL)
 533                 goto mem_failure;
 534         ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
 535 
 536         big = OBJ_PRI_DSA_BASE(object_p);
 537         if ((ptr = malloc(big->big_value_len)) == NULL)
 538                 goto mem_failure;
 539         ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
 540 
 541         big = OBJ_PRI_DSA_VALUE(object_p);
 542         if ((ptr = malloc(big->big_value_len)) == NULL)
 543                 goto mem_failure;
 544         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 545 
 546         (void) pthread_mutex_unlock(&object_p->object_mutex);
 547         return (CKR_OK);
 548 
 549 mem_failure:
 550         (void) pthread_mutex_unlock(&object_p->object_mutex);
 551         free_key_attributes(key);
 552         return (CKR_HOST_MEMORY);
 553 }
 554 
 555 
 556 /*
 557  * Convert a DSA public key object into a crypto_key structure.
 558  * Memory is allocated for each attribute stored in the crypto_key
 559  * structure.  Memory for the crypto_key structure is not
 560  * allocated.  Attributes can be freed by free_dsa_key_attributes().
 561  */
 562 CK_RV
 563 get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
 564 {
 565         biginteger_t *big;
 566         crypto_object_attribute_t *attrs, *cur_attr;
 567         char *ptr;
 568 
 569         (void) pthread_mutex_lock(&object_p->object_mutex);
 570         if (object_p->key_type != CKK_DSA ||
 571             object_p->class != CKO_PUBLIC_KEY) {
 572                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 573                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 574         }
 575 
 576         attrs = calloc(1,
 577             DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 578         if (attrs == NULL) {
 579                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 580                 return (CKR_HOST_MEMORY);
 581         }
 582 
 583         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 584         key->ck_count = DSA_ATTR_COUNT;
 585         key->ck_attrs = attrs;
 586 
 587         cur_attr = attrs;
 588         big = OBJ_PUB_DSA_PRIME(object_p);
 589         if ((ptr = malloc(big->big_value_len)) == NULL)
 590                 goto mem_failure;
 591         ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
 592 
 593         big = OBJ_PUB_DSA_SUBPRIME(object_p);
 594         if ((ptr = malloc(big->big_value_len)) == NULL)
 595                 goto mem_failure;
 596         ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
 597 
 598         big = OBJ_PUB_DSA_BASE(object_p);
 599         if ((ptr = malloc(big->big_value_len)) == NULL)
 600                 goto mem_failure;
 601         ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
 602 
 603         big = OBJ_PUB_DSA_VALUE(object_p);
 604         if ((ptr = malloc(big->big_value_len)) == NULL)
 605                 goto mem_failure;
 606         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 607 
 608         (void) pthread_mutex_unlock(&object_p->object_mutex);
 609         return (CKR_OK);
 610 
 611 mem_failure:
 612         (void) pthread_mutex_unlock(&object_p->object_mutex);
 613         free_key_attributes(key);
 614         return (CKR_HOST_MEMORY);
 615 }
 616 
 617 
 618 /*
 619  * Convert a EC private key object into a crypto_key structure.
 620  * Memory is allocated for each attribute stored in the crypto_key
 621  * structure.  Memory for the crypto_key structure is not
 622  * allocated.  Attributes can be freed by free_ec_key_attributes().
 623  */
 624 CK_RV
 625 get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
 626 {
 627         biginteger_t *big;
 628         crypto_object_attribute_t *attrs, *cur_attr;
 629         CK_ATTRIBUTE tmp;
 630         char *ptr;
 631         int rv;
 632 
 633         (void) pthread_mutex_lock(&object_p->object_mutex);
 634         if (object_p->key_type != CKK_EC ||
 635             object_p->class != CKO_PRIVATE_KEY) {
 636                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 637                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 638         }
 639 
 640         attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
 641         if (attrs == NULL) {
 642                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 643                 return (CKR_HOST_MEMORY);
 644         }
 645 
 646         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 647         key->ck_count = EC_ATTR_COUNT;
 648         key->ck_attrs = attrs;
 649 
 650         cur_attr = attrs;
 651         big = OBJ_PRI_EC_VALUE(object_p);
 652         if ((ptr = malloc(big->big_value_len)) == NULL) {
 653                 rv = CKR_HOST_MEMORY;
 654                 goto fail;
 655         }
 656         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 657 
 658         tmp.type = CKA_EC_PARAMS;
 659         tmp.pValue = NULL;
 660         rv = kernel_get_attribute(object_p, &tmp);
 661         if (rv != CKR_OK) {
 662                 goto fail;
 663         }
 664 
 665         tmp.pValue = malloc(tmp.ulValueLen);
 666         if (tmp.pValue == NULL) {
 667                 rv = CKR_HOST_MEMORY;
 668                 goto fail;
 669         }
 670 
 671         rv = kernel_get_attribute(object_p, &tmp);
 672         if (rv != CKR_OK) {
 673                 free(tmp.pValue);
 674                 goto fail;
 675         }
 676 
 677         cur_attr->oa_type = tmp.type;
 678         cur_attr->oa_value = tmp.pValue;
 679         cur_attr->oa_value_len = tmp.ulValueLen;
 680 
 681         (void) pthread_mutex_unlock(&object_p->object_mutex);
 682         return (CKR_OK);
 683 
 684 fail:
 685         (void) pthread_mutex_unlock(&object_p->object_mutex);
 686         free_key_attributes(key);
 687         return (rv);
 688 }
 689 
 690 /*
 691  * Convert an EC public key object into a crypto_key structure.
 692  * Memory is allocated for each attribute stored in the crypto_key
 693  * structure.  Memory for the crypto_key structure is not
 694  * allocated.  Attributes can be freed by free_ec_key_attributes().
 695  */
 696 CK_RV
 697 get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
 698 {
 699         biginteger_t *big;
 700         crypto_object_attribute_t *attrs, *cur_attr;
 701         CK_ATTRIBUTE tmp;
 702         char *ptr;
 703         int rv;
 704 
 705         (void) pthread_mutex_lock(&object_p->object_mutex);
 706         if (object_p->key_type != CKK_EC ||
 707             object_p->class != CKO_PUBLIC_KEY) {
 708                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 709                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 710         }
 711 
 712         attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
 713         if (attrs == NULL) {
 714                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 715                 return (CKR_HOST_MEMORY);
 716         }
 717 
 718         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 719         key->ck_count = EC_ATTR_COUNT;
 720         key->ck_attrs = attrs;
 721 
 722         cur_attr = attrs;
 723         big = OBJ_PUB_EC_POINT(object_p);
 724         if ((ptr = malloc(big->big_value_len)) == NULL) {
 725                 rv = CKR_HOST_MEMORY;
 726                 goto fail;
 727         }
 728         ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
 729 
 730         tmp.type = CKA_EC_PARAMS;
 731         tmp.pValue = NULL;
 732         rv = kernel_get_attribute(object_p, &tmp);
 733         if (rv != CKR_OK) {
 734                 goto fail;
 735         }
 736 
 737         tmp.pValue = malloc(tmp.ulValueLen);
 738         if (tmp.pValue == NULL) {
 739                 rv = CKR_HOST_MEMORY;
 740                 goto fail;
 741         }
 742 
 743         rv = kernel_get_attribute(object_p, &tmp);
 744         if (rv != CKR_OK) {
 745                 free(tmp.pValue);
 746                 goto fail;
 747         }
 748 
 749         cur_attr->oa_type = tmp.type;
 750         cur_attr->oa_value = tmp.pValue;
 751         cur_attr->oa_value_len = tmp.ulValueLen;
 752 
 753         (void) pthread_mutex_unlock(&object_p->object_mutex);
 754         return (CKR_OK);
 755 
 756 fail:
 757         (void) pthread_mutex_unlock(&object_p->object_mutex);
 758         free_key_attributes(key);
 759         return (rv);
 760 }
 761 
 762 /*
 763  * Convert an attribute template into an obj_attrs array.
 764  * Memory is allocated for each attribute stored in the obj_attrs.
 765  * The memory can be freed by free_object_attributes().
 766  *
 767  * If the boolean pointer is_token_obj is not NULL, the caller wants to
 768  * retrieve the value of the CKA_TOKEN attribute if it is specified in the
 769  * template.
 770  * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
 771  *   any key management function, is_token_obj should NOT be NULL.
 772  * - When this routine is called thru C_GetAttributeValue() or
 773  *   C_SetAttributeValue(), "is_token_obj" should be NULL.
 774  */
 775 CK_RV
 776 process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
 777     caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
 778 {
 779         crypto_object_attribute_t *attrs, *cur_attr;
 780         int i, cur_i;
 781         char *ptr;
 782         CK_RV rv;
 783         ssize_t value_len;
 784 
 785         if (ulCount == 0) {
 786                 obj_attrs = NULL;
 787                 return (CKR_OK);
 788         }
 789 
 790         attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
 791         if (attrs == NULL) {
 792                 return (CKR_HOST_MEMORY);
 793         }
 794 
 795         cur_attr = attrs;
 796         for (i = 0; i < ulCount; i++) {
 797                 /*
 798                  * The length of long attributes must be set correctly
 799                  * so providers can determine whether they came from 32
 800                  * or 64-bit applications.
 801                  */
 802                 switch (pTemplate[i].type) {
 803                 case CKA_CLASS:
 804                 case CKA_CERTIFICATE_TYPE:
 805                 case CKA_KEY_TYPE:
 806                 case CKA_MODULUS_BITS:
 807                 case CKA_HW_FEATURE_TYPE:
 808                         value_len = sizeof (ulong_t);
 809                         if (pTemplate[i].pValue != NULL &&
 810                             (pTemplate[i].ulValueLen < value_len)) {
 811                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 812                                 cur_i = i;
 813                                 goto fail_cleanup;
 814                         }
 815                         break;
 816                 default:
 817                         value_len = pTemplate[i].ulValueLen;
 818                 }
 819 
 820                 cur_attr->oa_type = pTemplate[i].type;
 821                 cur_attr->oa_value_len = value_len;
 822                 cur_attr->oa_value = NULL;
 823 
 824                 if ((pTemplate[i].pValue != NULL) &&
 825                     (pTemplate[i].ulValueLen > 0)) {
 826                         ptr = malloc(pTemplate[i].ulValueLen);
 827                         if (ptr == NULL) {
 828                                 rv = CKR_HOST_MEMORY;
 829                                 cur_i = i;
 830                                 goto fail_cleanup;
 831                         } else {
 832                                 (void) memcpy(ptr, pTemplate[i].pValue,
 833                                     pTemplate[i].ulValueLen);
 834                                 cur_attr->oa_value = ptr;
 835                         }
 836                 }
 837 
 838                 if ((is_token_obj != NULL) &&
 839                     (pTemplate[i].type == CKA_TOKEN)) {
 840                         /* Get the CKA_TOKEN attribute value. */
 841                         if (pTemplate[i].pValue == NULL) {
 842                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 843                                 cur_i = i;
 844                                 goto fail_cleanup;
 845                         } else {
 846                                 *is_token_obj =
 847                                     *(CK_BBOOL *)pTemplate[i].pValue;
 848                         }
 849                 }
 850 
 851                 cur_attr++;
 852         }
 853 
 854         *obj_attrs = (char *)attrs;
 855         return (CKR_OK);
 856 
 857 fail_cleanup:
 858         cur_attr = attrs;
 859         for (i = 0; i < cur_i; i++) {
 860                 if (cur_attr->oa_value != NULL) {
 861                         (void) free(cur_attr->oa_value);
 862                 }
 863                 cur_attr++;
 864         }
 865 
 866         (void) free(attrs);
 867         return (rv);
 868 }
 869 
 870 
 871 /*
 872  * Copy the attribute values from obj_attrs to pTemplate.
 873  * The obj_attrs is an image of the Template and is expected to have the
 874  * same attributes in the same order and each one of the attribute pValue
 875  * in obj_attr has enough space allocated for the corresponding valueLen
 876  * in pTemplate.
 877  */
 878 CK_RV
 879 get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
 880     caddr_t obj_attrs)
 881 {
 882         crypto_object_attribute_t *cur_attr;
 883         CK_RV rv = CKR_OK;
 884         int i;
 885 
 886         /* LINTED */
 887         cur_attr = (crypto_object_attribute_t *)obj_attrs;
 888         for (i = 0; i < ulCount; i++) {
 889                 if (pTemplate[i].type != cur_attr->oa_type) {
 890                         /* The attribute type doesn't match, this is bad. */
 891                         rv = CKR_FUNCTION_FAILED;
 892                         return (rv);
 893                 }
 894 
 895                 pTemplate[i].ulValueLen = cur_attr->oa_value_len;
 896 
 897                 if ((pTemplate[i].pValue != NULL) &&
 898                     ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
 899                         (void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
 900                             pTemplate[i].ulValueLen);
 901                 }
 902                 cur_attr++;
 903         }
 904 
 905         return (rv);
 906 }
 907 
 908 /*
 909  * Free the attribute storage in a crypto_object_attribute_t structure.
 910  */
 911 void
 912 free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
 913 {
 914         crypto_object_attribute_t *cur_attr;
 915         int i;
 916 
 917         if ((ulCount == 0) || (obj_attrs == NULL)) {
 918                 return;
 919         }
 920 
 921         /* LINTED */
 922         cur_attr = (crypto_object_attribute_t *)obj_attrs;
 923         for (i = 0; i < ulCount; i++) {
 924                 /* XXX check that oa_value > 0 */
 925                 if (cur_attr->oa_value != NULL) {
 926                         free(cur_attr->oa_value);
 927                 }
 928                 cur_attr++;
 929         }
 930 
 931         free(obj_attrs);
 932 }
 933 
 934 /*
 935  * This function is called by process_found_objects().  It will check the
 936  * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
 937  * initialize all the necessary fields in the object wrapper "objp".
 938  */
 939 static CK_RV
 940 create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
 941     kernel_object_t *objp,  crypto_object_id_t oid)
 942 {
 943         CK_RV  rv = CKR_OK;
 944         crypto_object_get_attribute_value_t obj_ga;
 945         boolean_t is_pri_obj;
 946         boolean_t is_token_obj;
 947         CK_BBOOL pri_value, token_value;
 948         CK_ATTRIBUTE  pTemplate[2];
 949         int r;
 950 
 951         /*
 952          * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
 953          * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
 954          */
 955         obj_ga.og_session = sp->k_session;
 956         obj_ga.og_handle = oid;
 957         obj_ga.og_count = 2;
 958 
 959         pTemplate[0].type = CKA_PRIVATE;
 960         pTemplate[0].pValue = &pri_value;
 961         pTemplate[0].ulValueLen = sizeof (pri_value);
 962         pTemplate[1].type = CKA_TOKEN;
 963         pTemplate[1].pValue = &token_value;
 964         pTemplate[1].ulValueLen = sizeof (token_value);
 965         rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
 966             NULL);
 967         if (rv != CKR_OK) {
 968                 return (rv);
 969         }
 970 
 971         while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
 972             &obj_ga)) < 0) {
 973                 if (errno != EINTR)
 974                         break;
 975         }
 976         if (r < 0) {
 977                 rv = CKR_FUNCTION_FAILED;
 978         } else {
 979                 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
 980         }
 981 
 982         if (rv == CKR_OK) {
 983                 rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
 984                 if (rv == CKR_OK) {
 985                         is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
 986                         is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
 987                 }
 988         }
 989 
 990         free_object_attributes(obj_ga.og_attributes, 2);
 991         if (rv != CKR_OK) {
 992                 return (rv);
 993         }
 994 
 995         /* Make sure it is a token object. */
 996         if (!is_token_obj) {
 997                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 998                 return (rv);
 999         }
1000 
1001         /* If it is a private object, make sure the user has logged in. */
1002         if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
1003                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1004                 return (rv);
1005         }
1006 
1007         objp->is_lib_obj = B_FALSE;
1008         objp->k_handle = oid;
1009         objp->bool_attr_mask |= TOKEN_BOOL_ON;
1010         if (is_pri_obj) {
1011                 objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1012         } else {
1013                 objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1014         }
1015 
1016         (void) pthread_mutex_init(&objp->object_mutex, NULL);
1017         objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1018         objp->session_handle = (CK_SESSION_HANDLE) sp;
1019 
1020         return (CKR_OK);
1021 }
1022 
1023 /*
1024  * This function processes the kernel object handles returned from the
1025  * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
1026  * and the number of object handles to the caller - C_FindObjects().
1027  * The caller acquires the slot lock and the session lock.
1028  */
1029 CK_RV
1030 process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
1031     CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
1032 {
1033         CK_RV rv = CKR_OK;
1034         crypto_object_id_t  *oid_p;
1035         kernel_slot_t *pslot;
1036         kernel_object_t *objp;
1037         kernel_object_t *objp1;
1038         kernel_object_t *new_tobj_list = NULL;
1039         kernel_session_t  *sp;
1040         CK_ULONG num_obj_found = 0;
1041         boolean_t is_in_lib;
1042         int i;
1043 
1044         if (obj_fu.fu_count == 0) {
1045                 *found_obj_count = 0;
1046                 return (CKR_OK);
1047         }
1048 
1049         pslot = slot_table[cur_sp->ses_slotid];
1050 
1051         /* LINTED */
1052         oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
1053         for (i = 0; i < obj_fu.fu_count; i++) {
1054                 is_in_lib = B_FALSE;
1055                 /*
1056                  * Check if this oid has an object wrapper in the library
1057                  * already.  First, search the slot's token object list.
1058                  */
1059                 objp = pslot->sl_tobj_list;
1060                 while (!is_in_lib && objp) {
1061                         if (objp->k_handle == *oid_p) {
1062                                 is_in_lib = B_TRUE;
1063                         } else {
1064                                 objp = objp->next;
1065                         }
1066                 }
1067 
1068                 /*
1069                  * If it is not in the slot's token object list,
1070                  * search it in all the sessions.
1071                  */
1072                 if (!is_in_lib) {
1073                         sp = pslot->sl_sess_list;
1074                         while (!is_in_lib && sp) {
1075                                 objp = sp->object_list;
1076                                 while (!is_in_lib && objp) {
1077                                         if (objp->k_handle == *oid_p) {
1078                                                 is_in_lib = B_TRUE;
1079                                         } else {
1080                                                 objp = objp->next;
1081                                         }
1082                                 }
1083                                 sp = sp->next;
1084                         }
1085                 }
1086 
1087                 /*
1088                  * If this object is in the library already, add its object
1089                  * wrapper to the returned find object list.
1090                  */
1091                 if (is_in_lib) {
1092                         obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1093                 }
1094 
1095                 /*
1096                  * If we still do not find it in the library.  This object
1097                  * must be a token object pre-existed in the HW provider.
1098                  * We need to create an object wrapper for it in the library.
1099                  */
1100                 if (!is_in_lib) {
1101                         objp1 = calloc(1, sizeof (kernel_object_t));
1102                         if (objp1 == NULL) {
1103                                 rv = CKR_HOST_MEMORY;
1104                                 goto failed_exit;
1105                         }
1106                         rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
1107                             *oid_p);
1108 
1109                         if (rv == CKR_OK) {
1110                                 /* Save the new object to the new_tobj_list. */
1111                                 if (new_tobj_list == NULL) {
1112                                         new_tobj_list = objp1;
1113                                         objp1->next = NULL;
1114                                         objp1->prev = NULL;
1115                                 } else {
1116                                         new_tobj_list->prev = objp1;
1117                                         objp1->next = new_tobj_list;
1118                                         objp1->prev = NULL;
1119                                         new_tobj_list = objp1;
1120                                 }
1121                         } else {
1122                                 /*
1123                                  * If create_new_tobj_in_lib() doesn't fail
1124                                  * with CKR_HOST_MEMORY, the failure should be
1125                                  * caused by the attributes' checking. We will
1126                                  * just ignore this object and continue on.
1127                                  */
1128                                 free(objp1);
1129                                 if (rv == CKR_HOST_MEMORY) {
1130                                         goto failed_exit;
1131                                 }
1132                         }
1133                 }
1134 
1135                 /* Process next one */
1136                 oid_p++;
1137         }
1138 
1139         /*
1140          * Add the newly created token object wrappers to the found object
1141          * list and to the slot's token object list.
1142          */
1143         if (new_tobj_list != NULL) {
1144                 /* Add to the obj_found array. */
1145                 objp = new_tobj_list;
1146                 while (objp) {
1147                         obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1148                         if (objp->next == NULL) {
1149                                 break;
1150                         }
1151                         objp = objp->next;
1152                 }
1153 
1154                 /* Add to the beginning of the slot's token object list. */
1155                 if (pslot->sl_tobj_list != NULL) {
1156                         objp->next = pslot->sl_tobj_list;
1157                         pslot->sl_tobj_list->prev = objp;
1158                 }
1159                 pslot->sl_tobj_list = new_tobj_list;
1160         }
1161 
1162         *found_obj_count = num_obj_found;
1163         return (CKR_OK);
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);
1205         obj_ga.og_attributes = (char *)&obj_attr;
1206 
1207         while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
1208             &obj_ga)) < 0) {
1209                 if (errno != EINTR)
1210                         break;
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;
1302                 if (mi_flags & CRYPTO_FG_SIGN)
1303                         flags |= CKF_SIGN;
1304                 if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
1305                         flags |= CKF_SIGN_RECOVER;
1306                 if (mi_flags & CRYPTO_FG_VERIFY)
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 }