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                         freezero(key->ck_attrs[i].oa_value,
 484                             key->ck_attrs[i].oa_value_len);
 485                 }
 486                 free(key->ck_attrs);
 487         }
 488 }
 489 
 490 
 491 /*
 492  * Convert a DSA private key object into a crypto_key structure.
 493  * Memory is allocated for each attribute stored in the crypto_key
 494  * structure.  Memory for the crypto_key structure is not
 495  * allocated.  Attributes can be freed by free_dsa_key_attributes().
 496  */
 497 CK_RV
 498 get_dsa_private_key(kernel_object_t *object_p, crypto_key_t *key)
 499 {
 500         biginteger_t *big;
 501         crypto_object_attribute_t *attrs, *cur_attr;
 502         char *ptr;
 503 
 504         (void) pthread_mutex_lock(&object_p->object_mutex);
 505         if (object_p->key_type != CKK_DSA ||
 506             object_p->class != CKO_PRIVATE_KEY) {
 507                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 508                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 509         }
 510 
 511         attrs = calloc(1,
 512             DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 513         if (attrs == NULL) {
 514                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 515                 return (CKR_HOST_MEMORY);
 516         }
 517 
 518         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 519         key->ck_count = DSA_ATTR_COUNT;
 520         key->ck_attrs = attrs;
 521 
 522         cur_attr = attrs;
 523         big = OBJ_PRI_DSA_PRIME(object_p);
 524         if ((ptr = malloc(big->big_value_len)) == NULL)
 525                 goto mem_failure;
 526         ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
 527 
 528         big = OBJ_PRI_DSA_SUBPRIME(object_p);
 529         if ((ptr = malloc(big->big_value_len)) == NULL)
 530                 goto mem_failure;
 531         ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
 532 
 533         big = OBJ_PRI_DSA_BASE(object_p);
 534         if ((ptr = malloc(big->big_value_len)) == NULL)
 535                 goto mem_failure;
 536         ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
 537 
 538         big = OBJ_PRI_DSA_VALUE(object_p);
 539         if ((ptr = malloc(big->big_value_len)) == NULL)
 540                 goto mem_failure;
 541         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 542 
 543         (void) pthread_mutex_unlock(&object_p->object_mutex);
 544         return (CKR_OK);
 545 
 546 mem_failure:
 547         (void) pthread_mutex_unlock(&object_p->object_mutex);
 548         free_key_attributes(key);
 549         return (CKR_HOST_MEMORY);
 550 }
 551 
 552 
 553 /*
 554  * Convert a DSA public key object into a crypto_key structure.
 555  * Memory is allocated for each attribute stored in the crypto_key
 556  * structure.  Memory for the crypto_key structure is not
 557  * allocated.  Attributes can be freed by free_dsa_key_attributes().
 558  */
 559 CK_RV
 560 get_dsa_public_key(kernel_object_t *object_p, crypto_key_t *key)
 561 {
 562         biginteger_t *big;
 563         crypto_object_attribute_t *attrs, *cur_attr;
 564         char *ptr;
 565 
 566         (void) pthread_mutex_lock(&object_p->object_mutex);
 567         if (object_p->key_type != CKK_DSA ||
 568             object_p->class != CKO_PUBLIC_KEY) {
 569                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 570                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 571         }
 572 
 573         attrs = calloc(1,
 574             DSA_ATTR_COUNT * sizeof (crypto_object_attribute_t));
 575         if (attrs == NULL) {
 576                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 577                 return (CKR_HOST_MEMORY);
 578         }
 579 
 580         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 581         key->ck_count = DSA_ATTR_COUNT;
 582         key->ck_attrs = attrs;
 583 
 584         cur_attr = attrs;
 585         big = OBJ_PUB_DSA_PRIME(object_p);
 586         if ((ptr = malloc(big->big_value_len)) == NULL)
 587                 goto mem_failure;
 588         ENCODE_ATTR(CKA_PRIME, big->big_value, big->big_value_len);
 589 
 590         big = OBJ_PUB_DSA_SUBPRIME(object_p);
 591         if ((ptr = malloc(big->big_value_len)) == NULL)
 592                 goto mem_failure;
 593         ENCODE_ATTR(CKA_SUBPRIME, big->big_value, big->big_value_len);
 594 
 595         big = OBJ_PUB_DSA_BASE(object_p);
 596         if ((ptr = malloc(big->big_value_len)) == NULL)
 597                 goto mem_failure;
 598         ENCODE_ATTR(CKA_BASE, big->big_value, big->big_value_len);
 599 
 600         big = OBJ_PUB_DSA_VALUE(object_p);
 601         if ((ptr = malloc(big->big_value_len)) == NULL)
 602                 goto mem_failure;
 603         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 604 
 605         (void) pthread_mutex_unlock(&object_p->object_mutex);
 606         return (CKR_OK);
 607 
 608 mem_failure:
 609         (void) pthread_mutex_unlock(&object_p->object_mutex);
 610         free_key_attributes(key);
 611         return (CKR_HOST_MEMORY);
 612 }
 613 
 614 
 615 /*
 616  * Convert a EC private key object into a crypto_key structure.
 617  * Memory is allocated for each attribute stored in the crypto_key
 618  * structure.  Memory for the crypto_key structure is not
 619  * allocated.  Attributes can be freed by free_ec_key_attributes().
 620  */
 621 CK_RV
 622 get_ec_private_key(kernel_object_t *object_p, crypto_key_t *key)
 623 {
 624         biginteger_t *big;
 625         crypto_object_attribute_t *attrs, *cur_attr;
 626         CK_ATTRIBUTE tmp;
 627         char *ptr;
 628         int rv;
 629 
 630         (void) pthread_mutex_lock(&object_p->object_mutex);
 631         if (object_p->key_type != CKK_EC ||
 632             object_p->class != CKO_PRIVATE_KEY) {
 633                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 634                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 635         }
 636 
 637         attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
 638         if (attrs == NULL) {
 639                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 640                 return (CKR_HOST_MEMORY);
 641         }
 642 
 643         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 644         key->ck_count = EC_ATTR_COUNT;
 645         key->ck_attrs = attrs;
 646 
 647         cur_attr = attrs;
 648         big = OBJ_PRI_EC_VALUE(object_p);
 649         if ((ptr = malloc(big->big_value_len)) == NULL) {
 650                 rv = CKR_HOST_MEMORY;
 651                 goto fail;
 652         }
 653         ENCODE_ATTR(CKA_VALUE, big->big_value, big->big_value_len);
 654 
 655         tmp.type = CKA_EC_PARAMS;
 656         tmp.pValue = NULL;
 657         rv = kernel_get_attribute(object_p, &tmp);
 658         if (rv != CKR_OK) {
 659                 goto fail;
 660         }
 661 
 662         tmp.pValue = malloc(tmp.ulValueLen);
 663         if (tmp.pValue == NULL) {
 664                 rv = CKR_HOST_MEMORY;
 665                 goto fail;
 666         }
 667 
 668         rv = kernel_get_attribute(object_p, &tmp);
 669         if (rv != CKR_OK) {
 670                 free(tmp.pValue);
 671                 goto fail;
 672         }
 673 
 674         cur_attr->oa_type = tmp.type;
 675         cur_attr->oa_value = tmp.pValue;
 676         cur_attr->oa_value_len = tmp.ulValueLen;
 677 
 678         (void) pthread_mutex_unlock(&object_p->object_mutex);
 679         return (CKR_OK);
 680 
 681 fail:
 682         (void) pthread_mutex_unlock(&object_p->object_mutex);
 683         free_key_attributes(key);
 684         return (rv);
 685 }
 686 
 687 /*
 688  * Convert an EC public key object into a crypto_key structure.
 689  * Memory is allocated for each attribute stored in the crypto_key
 690  * structure.  Memory for the crypto_key structure is not
 691  * allocated.  Attributes can be freed by free_ec_key_attributes().
 692  */
 693 CK_RV
 694 get_ec_public_key(kernel_object_t *object_p, crypto_key_t *key)
 695 {
 696         biginteger_t *big;
 697         crypto_object_attribute_t *attrs, *cur_attr;
 698         CK_ATTRIBUTE tmp;
 699         char *ptr;
 700         int rv;
 701 
 702         (void) pthread_mutex_lock(&object_p->object_mutex);
 703         if (object_p->key_type != CKK_EC ||
 704             object_p->class != CKO_PUBLIC_KEY) {
 705                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 706                 return (CKR_ATTRIBUTE_TYPE_INVALID);
 707         }
 708 
 709         attrs = calloc(EC_ATTR_COUNT, sizeof (crypto_object_attribute_t));
 710         if (attrs == NULL) {
 711                 (void) pthread_mutex_unlock(&object_p->object_mutex);
 712                 return (CKR_HOST_MEMORY);
 713         }
 714 
 715         key->ck_format = CRYPTO_KEY_ATTR_LIST;
 716         key->ck_count = EC_ATTR_COUNT;
 717         key->ck_attrs = attrs;
 718 
 719         cur_attr = attrs;
 720         big = OBJ_PUB_EC_POINT(object_p);
 721         if ((ptr = malloc(big->big_value_len)) == NULL) {
 722                 rv = CKR_HOST_MEMORY;
 723                 goto fail;
 724         }
 725         ENCODE_ATTR(CKA_EC_POINT, big->big_value, big->big_value_len);
 726 
 727         tmp.type = CKA_EC_PARAMS;
 728         tmp.pValue = NULL;
 729         rv = kernel_get_attribute(object_p, &tmp);
 730         if (rv != CKR_OK) {
 731                 goto fail;
 732         }
 733 
 734         tmp.pValue = malloc(tmp.ulValueLen);
 735         if (tmp.pValue == NULL) {
 736                 rv = CKR_HOST_MEMORY;
 737                 goto fail;
 738         }
 739 
 740         rv = kernel_get_attribute(object_p, &tmp);
 741         if (rv != CKR_OK) {
 742                 free(tmp.pValue);
 743                 goto fail;
 744         }
 745 
 746         cur_attr->oa_type = tmp.type;
 747         cur_attr->oa_value = tmp.pValue;
 748         cur_attr->oa_value_len = tmp.ulValueLen;
 749 
 750         (void) pthread_mutex_unlock(&object_p->object_mutex);
 751         return (CKR_OK);
 752 
 753 fail:
 754         (void) pthread_mutex_unlock(&object_p->object_mutex);
 755         free_key_attributes(key);
 756         return (rv);
 757 }
 758 
 759 /*
 760  * Convert an attribute template into an obj_attrs array.
 761  * Memory is allocated for each attribute stored in the obj_attrs.
 762  * The memory can be freed by free_object_attributes().
 763  *
 764  * If the boolean pointer is_token_obj is not NULL, the caller wants to
 765  * retrieve the value of the CKA_TOKEN attribute if it is specified in the
 766  * template.
 767  * - When this routine is called thru C_CreateObject(), C_CopyObject(), or
 768  *   any key management function, is_token_obj should NOT be NULL.
 769  * - When this routine is called thru C_GetAttributeValue() or
 770  *   C_SetAttributeValue(), "is_token_obj" should be NULL.
 771  */
 772 CK_RV
 773 process_object_attributes(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
 774     caddr_t *obj_attrs, CK_BBOOL *is_token_obj)
 775 {
 776         crypto_object_attribute_t *attrs, *cur_attr;
 777         int i, cur_i;
 778         char *ptr;
 779         CK_RV rv;
 780         ssize_t value_len;
 781 
 782         if (ulCount == 0) {
 783                 obj_attrs = NULL;
 784                 return (CKR_OK);
 785         }
 786 
 787         attrs = calloc(1, ulCount * sizeof (crypto_object_attribute_t));
 788         if (attrs == NULL) {
 789                 return (CKR_HOST_MEMORY);
 790         }
 791 
 792         cur_attr = attrs;
 793         for (i = 0; i < ulCount; i++) {
 794                 /*
 795                  * The length of long attributes must be set correctly
 796                  * so providers can determine whether they came from 32
 797                  * or 64-bit applications.
 798                  */
 799                 switch (pTemplate[i].type) {
 800                 case CKA_CLASS:
 801                 case CKA_CERTIFICATE_TYPE:
 802                 case CKA_KEY_TYPE:
 803                 case CKA_MODULUS_BITS:
 804                 case CKA_HW_FEATURE_TYPE:
 805                         value_len = sizeof (ulong_t);
 806                         if (pTemplate[i].pValue != NULL &&
 807                             (pTemplate[i].ulValueLen < value_len)) {
 808                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 809                                 cur_i = i;
 810                                 goto fail_cleanup;
 811                         }
 812                         break;
 813                 default:
 814                         value_len = pTemplate[i].ulValueLen;
 815                 }
 816 
 817                 cur_attr->oa_type = pTemplate[i].type;
 818                 cur_attr->oa_value_len = value_len;
 819                 cur_attr->oa_value = NULL;
 820 
 821                 if ((pTemplate[i].pValue != NULL) &&
 822                     (pTemplate[i].ulValueLen > 0)) {
 823                         ptr = malloc(pTemplate[i].ulValueLen);
 824                         if (ptr == NULL) {
 825                                 rv = CKR_HOST_MEMORY;
 826                                 cur_i = i;
 827                                 goto fail_cleanup;
 828                         } else {
 829                                 (void) memcpy(ptr, pTemplate[i].pValue,
 830                                     pTemplate[i].ulValueLen);
 831                                 cur_attr->oa_value = ptr;
 832                         }
 833                 }
 834 
 835                 if ((is_token_obj != NULL) &&
 836                     (pTemplate[i].type == CKA_TOKEN)) {
 837                         /* Get the CKA_TOKEN attribute value. */
 838                         if (pTemplate[i].pValue == NULL) {
 839                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 840                                 cur_i = i;
 841                                 goto fail_cleanup;
 842                         } else {
 843                                 *is_token_obj =
 844                                     *(CK_BBOOL *)pTemplate[i].pValue;
 845                         }
 846                 }
 847 
 848                 cur_attr++;
 849         }
 850 
 851         *obj_attrs = (char *)attrs;
 852         return (CKR_OK);
 853 
 854 fail_cleanup:
 855         cur_attr = attrs;
 856         for (i = 0; i < cur_i; i++) {
 857                 if (cur_attr->oa_value != NULL) {
 858                         (void) free(cur_attr->oa_value);
 859                 }
 860                 cur_attr++;
 861         }
 862 
 863         (void) free(attrs);
 864         return (rv);
 865 }
 866 
 867 
 868 /*
 869  * Copy the attribute values from obj_attrs to pTemplate.
 870  * The obj_attrs is an image of the Template and is expected to have the
 871  * same attributes in the same order and each one of the attribute pValue
 872  * in obj_attr has enough space allocated for the corresponding valueLen
 873  * in pTemplate.
 874  */
 875 CK_RV
 876 get_object_attributes(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
 877     caddr_t obj_attrs)
 878 {
 879         crypto_object_attribute_t *cur_attr;
 880         CK_RV rv = CKR_OK;
 881         int i;
 882 
 883         /* LINTED */
 884         cur_attr = (crypto_object_attribute_t *)obj_attrs;
 885         for (i = 0; i < ulCount; i++) {
 886                 if (pTemplate[i].type != cur_attr->oa_type) {
 887                         /* The attribute type doesn't match, this is bad. */
 888                         rv = CKR_FUNCTION_FAILED;
 889                         return (rv);
 890                 }
 891 
 892                 pTemplate[i].ulValueLen = cur_attr->oa_value_len;
 893 
 894                 if ((pTemplate[i].pValue != NULL) &&
 895                     ((CK_LONG)pTemplate[i].ulValueLen != -1)) {
 896                         (void) memcpy(pTemplate[i].pValue, cur_attr->oa_value,
 897                             pTemplate[i].ulValueLen);
 898                 }
 899                 cur_attr++;
 900         }
 901 
 902         return (rv);
 903 }
 904 
 905 /*
 906  * Free the attribute storage in a crypto_object_attribute_t structure.
 907  */
 908 void
 909 free_object_attributes(caddr_t obj_attrs, CK_ULONG ulCount)
 910 {
 911         crypto_object_attribute_t *cur_attr;
 912         int i;
 913 
 914         if ((ulCount == 0) || (obj_attrs == NULL)) {
 915                 return;
 916         }
 917 
 918         /* LINTED */
 919         cur_attr = (crypto_object_attribute_t *)obj_attrs;
 920         for (i = 0; i < ulCount; i++) {
 921                 /* XXX check that oa_value > 0 */
 922                 if (cur_attr->oa_value != NULL) {
 923                         free(cur_attr->oa_value);
 924                 }
 925                 cur_attr++;
 926         }
 927 
 928         free(obj_attrs);
 929 }
 930 
 931 /*
 932  * This function is called by process_found_objects().  It will check the
 933  * CKA_PRIVATE and CKA_TOKEN attributes for the kernel object "oid", then
 934  * initialize all the necessary fields in the object wrapper "objp".
 935  */
 936 static CK_RV
 937 create_new_tobj_in_lib(kernel_slot_t *pslot, kernel_session_t *sp,
 938     kernel_object_t *objp,  crypto_object_id_t oid)
 939 {
 940         CK_RV  rv = CKR_OK;
 941         crypto_object_get_attribute_value_t obj_ga;
 942         boolean_t is_pri_obj;
 943         boolean_t is_token_obj;
 944         CK_BBOOL pri_value, token_value;
 945         CK_ATTRIBUTE  pTemplate[2];
 946         int r;
 947 
 948         /*
 949          * Make a CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE ioctl call to get this
 950          * kernel object's attribute values for CKA_PRIVATE and CKA_TOKEN.
 951          */
 952         obj_ga.og_session = sp->k_session;
 953         obj_ga.og_handle = oid;
 954         obj_ga.og_count = 2;
 955 
 956         pTemplate[0].type = CKA_PRIVATE;
 957         pTemplate[0].pValue = &pri_value;
 958         pTemplate[0].ulValueLen = sizeof (pri_value);
 959         pTemplate[1].type = CKA_TOKEN;
 960         pTemplate[1].pValue = &token_value;
 961         pTemplate[1].ulValueLen = sizeof (token_value);
 962         rv = process_object_attributes(pTemplate, 2, &obj_ga.og_attributes,
 963             NULL);
 964         if (rv != CKR_OK) {
 965                 return (rv);
 966         }
 967 
 968         while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
 969             &obj_ga)) < 0) {
 970                 if (errno != EINTR)
 971                         break;
 972         }
 973         if (r < 0) {
 974                 rv = CKR_FUNCTION_FAILED;
 975         } else {
 976                 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
 977         }
 978 
 979         if (rv == CKR_OK) {
 980                 rv = get_object_attributes(pTemplate, 2, obj_ga.og_attributes);
 981                 if (rv == CKR_OK) {
 982                         is_pri_obj = *(CK_BBOOL *)pTemplate[0].pValue;
 983                         is_token_obj = *(CK_BBOOL *)pTemplate[1].pValue;
 984                 }
 985         }
 986 
 987         free_object_attributes(obj_ga.og_attributes, 2);
 988         if (rv != CKR_OK) {
 989                 return (rv);
 990         }
 991 
 992         /* Make sure it is a token object. */
 993         if (!is_token_obj) {
 994                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
 995                 return (rv);
 996         }
 997 
 998         /* If it is a private object, make sure the user has logged in. */
 999         if (is_pri_obj && (pslot->sl_state != CKU_USER)) {
1000                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1001                 return (rv);
1002         }
1003 
1004         objp->is_lib_obj = B_FALSE;
1005         objp->k_handle = oid;
1006         objp->bool_attr_mask |= TOKEN_BOOL_ON;
1007         if (is_pri_obj) {
1008                 objp->bool_attr_mask |= PRIVATE_BOOL_ON;
1009         } else {
1010                 objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
1011         }
1012 
1013         (void) pthread_mutex_init(&objp->object_mutex, NULL);
1014         objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
1015         objp->session_handle = (CK_SESSION_HANDLE) sp;
1016 
1017         return (CKR_OK);
1018 }
1019 
1020 /*
1021  * This function processes the kernel object handles returned from the
1022  * CRYPTO_OBJECT_FIND_UPDATE ioctl and returns an object handle list
1023  * and the number of object handles to the caller - C_FindObjects().
1024  * The caller acquires the slot lock and the session lock.
1025  */
1026 CK_RV
1027 process_found_objects(kernel_session_t *cur_sp, CK_OBJECT_HANDLE *obj_found,
1028     CK_ULONG *found_obj_count, crypto_object_find_update_t obj_fu)
1029 {
1030         CK_RV rv = CKR_OK;
1031         crypto_object_id_t  *oid_p;
1032         kernel_slot_t *pslot;
1033         kernel_object_t *objp;
1034         kernel_object_t *objp1;
1035         kernel_object_t *new_tobj_list = NULL;
1036         kernel_session_t  *sp;
1037         CK_ULONG num_obj_found = 0;
1038         boolean_t is_in_lib;
1039         int i;
1040 
1041         if (obj_fu.fu_count == 0) {
1042                 *found_obj_count = 0;
1043                 return (CKR_OK);
1044         }
1045 
1046         pslot = slot_table[cur_sp->ses_slotid];
1047 
1048         /* LINTED */
1049         oid_p = (crypto_object_id_t *)obj_fu.fu_handles;
1050         for (i = 0; i < obj_fu.fu_count; i++) {
1051                 is_in_lib = B_FALSE;
1052                 /*
1053                  * Check if this oid has an object wrapper in the library
1054                  * already.  First, search the slot's token object list.
1055                  */
1056                 objp = pslot->sl_tobj_list;
1057                 while (!is_in_lib && objp) {
1058                         if (objp->k_handle == *oid_p) {
1059                                 is_in_lib = B_TRUE;
1060                         } else {
1061                                 objp = objp->next;
1062                         }
1063                 }
1064 
1065                 /*
1066                  * If it is not in the slot's token object list,
1067                  * search it in all the sessions.
1068                  */
1069                 if (!is_in_lib) {
1070                         sp = pslot->sl_sess_list;
1071                         while (!is_in_lib && sp) {
1072                                 objp = sp->object_list;
1073                                 while (!is_in_lib && objp) {
1074                                         if (objp->k_handle == *oid_p) {
1075                                                 is_in_lib = B_TRUE;
1076                                         } else {
1077                                                 objp = objp->next;
1078                                         }
1079                                 }
1080                                 sp = sp->next;
1081                         }
1082                 }
1083 
1084                 /*
1085                  * If this object is in the library already, add its object
1086                  * wrapper to the returned find object list.
1087                  */
1088                 if (is_in_lib) {
1089                         obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1090                 }
1091 
1092                 /*
1093                  * If we still do not find it in the library.  This object
1094                  * must be a token object pre-existed in the HW provider.
1095                  * We need to create an object wrapper for it in the library.
1096                  */
1097                 if (!is_in_lib) {
1098                         objp1 = calloc(1, sizeof (kernel_object_t));
1099                         if (objp1 == NULL) {
1100                                 rv = CKR_HOST_MEMORY;
1101                                 goto failed_exit;
1102                         }
1103                         rv = create_new_tobj_in_lib(pslot, cur_sp, objp1,
1104                             *oid_p);
1105 
1106                         if (rv == CKR_OK) {
1107                                 /* Save the new object to the new_tobj_list. */
1108                                 if (new_tobj_list == NULL) {
1109                                         new_tobj_list = objp1;
1110                                         objp1->next = NULL;
1111                                         objp1->prev = NULL;
1112                                 } else {
1113                                         new_tobj_list->prev = objp1;
1114                                         objp1->next = new_tobj_list;
1115                                         objp1->prev = NULL;
1116                                         new_tobj_list = objp1;
1117                                 }
1118                         } else {
1119                                 /*
1120                                  * If create_new_tobj_in_lib() doesn't fail
1121                                  * with CKR_HOST_MEMORY, the failure should be
1122                                  * caused by the attributes' checking. We will
1123                                  * just ignore this object and continue on.
1124                                  */
1125                                 free(objp1);
1126                                 if (rv == CKR_HOST_MEMORY) {
1127                                         goto failed_exit;
1128                                 }
1129                         }
1130                 }
1131 
1132                 /* Process next one */
1133                 oid_p++;
1134         }
1135 
1136         /*
1137          * Add the newly created token object wrappers to the found object
1138          * list and to the slot's token object list.
1139          */
1140         if (new_tobj_list != NULL) {
1141                 /* Add to the obj_found array. */
1142                 objp = new_tobj_list;
1143                 while (objp) {
1144                         obj_found[num_obj_found++] = (CK_OBJECT_HANDLE)objp;
1145                         if (objp->next == NULL) {
1146                                 break;
1147                         }
1148                         objp = objp->next;
1149                 }
1150 
1151                 /* Add to the beginning of the slot's token object list. */
1152                 if (pslot->sl_tobj_list != NULL) {
1153                         objp->next = pslot->sl_tobj_list;
1154                         pslot->sl_tobj_list->prev = objp;
1155                 }
1156                 pslot->sl_tobj_list = new_tobj_list;
1157         }
1158 
1159         *found_obj_count = num_obj_found;
1160         return (CKR_OK);
1161 
1162 failed_exit:
1163 
1164         /* Free the newly created token object wrappers. */
1165         objp = new_tobj_list;
1166         while (objp) {
1167                 objp1 = objp->next;
1168                 (void) pthread_mutex_destroy(&objp->object_mutex);
1169                 free(objp);
1170                 objp = objp1;
1171         }
1172 
1173         return (rv);
1174 }
1175 
1176 
1177 /*
1178  * Get the value of the CKA_PRIVATE attribute for the object just returned
1179  * from the HW provider.  This function will be called by any function
1180  * that creates a new object, because the CKA_PRIVATE value of an object is
1181  * token specific.  The CKA_PRIVATE attribute value of the new object will be
1182  * stored in the object structure in the library, which will be used later at
1183  * C_Logout to clean up all private objects.
1184  */
1185 CK_RV
1186 get_cka_private_value(kernel_session_t *sp, crypto_object_id_t oid,
1187     CK_BBOOL *is_pri_obj)
1188 {
1189         CK_RV  rv = CKR_OK;
1190         crypto_object_get_attribute_value_t obj_ga;
1191         crypto_object_attribute_t obj_attr;
1192         CK_BBOOL pri_value;
1193         int r;
1194 
1195         obj_ga.og_session = sp->k_session;
1196         obj_ga.og_handle = oid;
1197         obj_ga.og_count = 1;
1198 
1199         obj_attr.oa_type = CKA_PRIVATE;
1200         obj_attr.oa_value = (char *)&pri_value;
1201         obj_attr.oa_value_len = sizeof (CK_BBOOL);
1202         obj_ga.og_attributes = (char *)&obj_attr;
1203 
1204         while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
1205             &obj_ga)) < 0) {
1206                 if (errno != EINTR)
1207                         break;
1208         }
1209         if (r < 0) {
1210                 rv = CKR_FUNCTION_FAILED;
1211         } else {
1212                 rv = crypto2pkcs11_error_number(obj_ga.og_return_value);
1213         }
1214 
1215         if (rv == CKR_OK) {
1216                 *is_pri_obj = *(CK_BBOOL *)obj_attr.oa_value;
1217         }
1218 
1219         return (rv);
1220 }
1221 
1222 
1223 CK_RV
1224 get_mechanism_info(kernel_slot_t *pslot, CK_MECHANISM_TYPE type,
1225     CK_MECHANISM_INFO_PTR pInfo, uint32_t *k_mi_flags)
1226 {
1227         crypto_get_provider_mechanism_info_t mechanism_info;
1228         const char *string;
1229         CK_FLAGS flags, mi_flags;
1230         CK_RV rv;
1231         int r;
1232         char buf[11];   /* Num chars for representing ulong in ASCII */
1233 
1234         if (type >= CKM_VENDOR_DEFINED) {
1235                 /* allocate/build a string containing the mechanism number */
1236                 (void) snprintf(buf, sizeof (buf), "%#lx", type);
1237                 string = buf;
1238         } else {
1239                 string = pkcs11_mech2str(type);
1240         }
1241 
1242         if (string == NULL)
1243                 return (CKR_MECHANISM_INVALID);
1244 
1245         (void) strcpy(mechanism_info.mi_mechanism_name, string);
1246         mechanism_info.mi_provider_id = pslot->sl_provider_id;
1247 
1248         while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
1249             &mechanism_info)) < 0) {
1250                 if (errno != EINTR)
1251                         break;
1252         }
1253         if (r < 0) {
1254                 rv = CKR_FUNCTION_FAILED;
1255         } else {
1256                 rv = crypto2pkcs11_error_number(
1257                     mechanism_info.mi_return_value);
1258         }
1259 
1260         if (rv != CKR_OK) {
1261                 return (rv);
1262         }
1263 
1264         /*
1265          * Atomic flags are not part of PKCS#11 so we filter
1266          * them out here.
1267          */
1268         mi_flags = mechanism_info.mi_flags;
1269         mi_flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
1270             CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
1271             CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
1272             CRYPTO_FG_SIGN_RECOVER_ATOMIC |
1273             CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
1274             CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
1275             CRYPTO_FG_MAC_DECRYPT_ATOMIC);
1276 
1277         if (mi_flags == 0) {
1278                 return (CKR_MECHANISM_INVALID);
1279         }
1280 
1281         if (rv == CKR_OK) {
1282                 /* set the value of k_mi_flags first */
1283                 *k_mi_flags = mi_flags;
1284 
1285                 /* convert KEF flags into pkcs11 flags */
1286                 flags = CKF_HW;
1287                 if (mi_flags & CRYPTO_FG_ENCRYPT)
1288                         flags |= CKF_ENCRYPT;
1289                 if (mi_flags & CRYPTO_FG_DECRYPT) {
1290                         flags |= CKF_DECRYPT;
1291                         /*
1292                          * Since we'll be emulating C_UnwrapKey() for some
1293                          * cases, we can go ahead and claim CKF_UNWRAP
1294                          */
1295                         flags |= CKF_UNWRAP;
1296                 }
1297                 if (mi_flags & CRYPTO_FG_DIGEST)
1298                         flags |= CKF_DIGEST;
1299                 if (mi_flags & CRYPTO_FG_SIGN)
1300                         flags |= CKF_SIGN;
1301                 if (mi_flags & CRYPTO_FG_SIGN_RECOVER)
1302                         flags |= CKF_SIGN_RECOVER;
1303                 if (mi_flags & CRYPTO_FG_VERIFY)
1304                         flags |= CKF_VERIFY;
1305                 if (mi_flags & CRYPTO_FG_VERIFY_RECOVER)
1306                         flags |= CKF_VERIFY_RECOVER;
1307                 if (mi_flags & CRYPTO_FG_GENERATE)
1308                         flags |= CKF_GENERATE;
1309                 if (mi_flags & CRYPTO_FG_GENERATE_KEY_PAIR)
1310                         flags |= CKF_GENERATE_KEY_PAIR;
1311                 if (mi_flags & CRYPTO_FG_WRAP)
1312                         flags |= CKF_WRAP;
1313                 if (mi_flags & CRYPTO_FG_UNWRAP)
1314                         flags |= CKF_UNWRAP;
1315                 if (mi_flags & CRYPTO_FG_DERIVE)
1316                         flags |= CKF_DERIVE;
1317 
1318                 pInfo->ulMinKeySize = mechanism_info.mi_min_key_size;
1319                 pInfo->ulMaxKeySize = mechanism_info.mi_max_key_size;
1320                 pInfo->flags = flags;
1321 
1322         }
1323 
1324         return (rv);
1325 }