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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  * Copyright (c) 2018, Joyent, Inc.
  26  */
  27 
  28 #include <stdlib.h>
  29 #include <string.h>
  30 #include <security/cryptoki.h>
  31 #include <sys/crypto/common.h>
  32 #include <arcfour.h>
  33 #include <aes_impl.h>
  34 #include <blowfish_impl.h>
  35 #include <bignum.h>
  36 #include <des_impl.h>
  37 #include <rsa_impl.h>
  38 #include "softGlobal.h"
  39 #include "softObject.h"
  40 #include "softSession.h"
  41 #include "softKeystore.h"
  42 #include "softKeystoreUtil.h"
  43 #include "softCrypt.h"
  44 
  45 
  46 /*
  47  * This attribute table is used by the soft_lookup_attr()
  48  * to validate the attributes.
  49  */
  50 CK_ATTRIBUTE_TYPE attr_map[] = {
  51         CKA_PRIVATE,
  52         CKA_LABEL,
  53         CKA_APPLICATION,
  54         CKA_OBJECT_ID,
  55         CKA_CERTIFICATE_TYPE,
  56         CKA_ISSUER,
  57         CKA_SERIAL_NUMBER,
  58         CKA_AC_ISSUER,
  59         CKA_OWNER,
  60         CKA_ATTR_TYPES,
  61         CKA_SUBJECT,
  62         CKA_ID,
  63         CKA_SENSITIVE,
  64         CKA_START_DATE,
  65         CKA_END_DATE,
  66         CKA_MODULUS,
  67         CKA_MODULUS_BITS,
  68         CKA_PUBLIC_EXPONENT,
  69         CKA_PRIVATE_EXPONENT,
  70         CKA_PRIME_1,
  71         CKA_PRIME_2,
  72         CKA_EXPONENT_1,
  73         CKA_EXPONENT_2,
  74         CKA_COEFFICIENT,
  75         CKA_PRIME,
  76         CKA_SUBPRIME,
  77         CKA_BASE,
  78         CKA_EXTRACTABLE,
  79         CKA_LOCAL,
  80         CKA_NEVER_EXTRACTABLE,
  81         CKA_ALWAYS_SENSITIVE,
  82         CKA_MODIFIABLE,
  83         CKA_ECDSA_PARAMS,
  84         CKA_EC_PARAMS,
  85         CKA_EC_POINT,
  86         CKA_SECONDARY_AUTH,
  87         CKA_AUTH_PIN_FLAGS,
  88         CKA_HW_FEATURE_TYPE,
  89         CKA_RESET_ON_INIT,
  90         CKA_HAS_RESET
  91 };
  92 
  93 /*
  94  * attributes that exists only in public key objects
  95  * Note: some attributes may also exist in one or two
  96  *       other object classes, but they are also listed
  97  *       because not all object have them.
  98  */
  99 CK_ATTRIBUTE_TYPE PUB_KEY_ATTRS[] =
 100 {
 101         CKA_SUBJECT,
 102         CKA_ENCRYPT,
 103         CKA_WRAP,
 104         CKA_VERIFY,
 105         CKA_VERIFY_RECOVER,
 106         CKA_MODULUS,
 107         CKA_MODULUS_BITS,
 108         CKA_PUBLIC_EXPONENT,
 109         CKA_PRIME,
 110         CKA_SUBPRIME,
 111         CKA_BASE,
 112         CKA_TRUSTED,
 113         CKA_ECDSA_PARAMS,
 114         CKA_EC_PARAMS,
 115         CKA_EC_POINT
 116 };
 117 
 118 /*
 119  * attributes that exists only in private key objects
 120  * Note: some attributes may also exist in one or two
 121  *       other object classes, but they are also listed
 122  *       because not all object have them.
 123  */
 124 CK_ATTRIBUTE_TYPE PRIV_KEY_ATTRS[] =
 125 {
 126         CKA_DECRYPT,
 127         CKA_UNWRAP,
 128         CKA_SIGN,
 129         CKA_SIGN_RECOVER,
 130         CKA_MODULUS,
 131         CKA_PUBLIC_EXPONENT,
 132         CKA_PRIVATE_EXPONENT,
 133         CKA_PRIME,
 134         CKA_SUBPRIME,
 135         CKA_BASE,
 136         CKA_PRIME_1,
 137         CKA_PRIME_2,
 138         CKA_EXPONENT_1,
 139         CKA_EXPONENT_2,
 140         CKA_COEFFICIENT,
 141         CKA_VALUE_BITS,
 142         CKA_SUBJECT,
 143         CKA_SENSITIVE,
 144         CKA_EXTRACTABLE,
 145         CKA_NEVER_EXTRACTABLE,
 146         CKA_ALWAYS_SENSITIVE,
 147         CKA_EC_PARAMS
 148 };
 149 
 150 /*
 151  * attributes that exists only in secret key objects
 152  * Note: some attributes may also exist in one or two
 153  *       other object classes, but they are also listed
 154  *       because not all object have them.
 155  */
 156 CK_ATTRIBUTE_TYPE SECRET_KEY_ATTRS[] =
 157 {
 158         CKA_VALUE_LEN,
 159         CKA_ENCRYPT,
 160         CKA_DECRYPT,
 161         CKA_WRAP,
 162         CKA_UNWRAP,
 163         CKA_SIGN,
 164         CKA_VERIFY,
 165         CKA_SENSITIVE,
 166         CKA_EXTRACTABLE,
 167         CKA_NEVER_EXTRACTABLE,
 168         CKA_ALWAYS_SENSITIVE
 169 };
 170 
 171 /*
 172  * attributes that exists only in domain parameter objects
 173  * Note: some attributes may also exist in one or two
 174  *       other object classes, but they are also listed
 175  *       because not all object have them.
 176  */
 177 CK_ATTRIBUTE_TYPE DOMAIN_ATTRS[] =
 178 {
 179         CKA_PRIME,
 180         CKA_SUBPRIME,
 181         CKA_BASE,
 182         CKA_PRIME_BITS,
 183         CKA_SUBPRIME_BITS,
 184         CKA_SUB_PRIME_BITS
 185 };
 186 
 187 /*
 188  * attributes that exists only in hardware feature objects
 189  *
 190  */
 191 CK_ATTRIBUTE_TYPE HARDWARE_ATTRS[] =
 192 {
 193         CKA_HW_FEATURE_TYPE,
 194         CKA_RESET_ON_INIT,
 195         CKA_HAS_RESET
 196 };
 197 
 198 /*
 199  * attributes that exists only in certificate objects
 200  */
 201 CK_ATTRIBUTE_TYPE CERT_ATTRS[] =
 202 {
 203         CKA_CERTIFICATE_TYPE,
 204         CKA_TRUSTED,
 205         CKA_SUBJECT,
 206         CKA_ID,
 207         CKA_ISSUER,
 208         CKA_AC_ISSUER,
 209         CKA_SERIAL_NUMBER,
 210         CKA_OWNER,
 211         CKA_ATTR_TYPES
 212 };
 213 
 214 
 215 /*
 216  * Validate the attribute by using binary search algorithm.
 217  */
 218 CK_RV
 219 soft_lookup_attr(CK_ATTRIBUTE_TYPE type)
 220 {
 221 
 222         size_t lower, middle, upper;
 223 
 224         lower = 0;
 225         upper = (sizeof (attr_map) / sizeof (CK_ATTRIBUTE_TYPE)) - 1;
 226 
 227         while (lower <= upper) {
 228                 /* Always starts from middle. */
 229                 middle = (lower + upper) / 2;
 230 
 231                 if (type > attr_map[middle]) {
 232                         /* Adjust the lower bound to upper half. */
 233                         lower = middle + 1;
 234                         continue;
 235                 }
 236 
 237                 if (type == attr_map[middle]) {
 238                         /* Found it. */
 239                         return (CKR_OK);
 240                 }
 241 
 242                 if (type < attr_map[middle]) {
 243                         /* Adjust the upper bound to lower half. */
 244                         upper = middle - 1;
 245                         continue;
 246                 }
 247         }
 248 
 249         /* Failed to find the matching attribute from the attribute table. */
 250         return (CKR_ATTRIBUTE_TYPE_INVALID);
 251 }
 252 
 253 
 254 /*
 255  * Validate the attribute by using the following search algorithm:
 256  *
 257  * 1) Search for the most frequently used attributes first.
 258  * 2) If not found, search for the usage-purpose attributes - these
 259  *    attributes have dense set of values, therefore compiler will
 260  *    optimize it with a branch table and branch to the appropriate
 261  *    case.
 262  * 3) If still not found, use binary search for the rest of the
 263  *    attributes in the attr_map[] table.
 264  */
 265 CK_RV
 266 soft_validate_attr(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
 267         CK_OBJECT_CLASS *class)
 268 {
 269 
 270         CK_ULONG i;
 271         CK_RV rv = CKR_OK;
 272 
 273         for (i = 0; i < ulAttrNum; i++) {
 274                 /* First tier search */
 275                 switch (template[i].type) {
 276                 case CKA_CLASS:
 277                         *class = *((CK_OBJECT_CLASS*)template[i].pValue);
 278                         break;
 279                 case CKA_TOKEN:
 280                         break;
 281                 case CKA_KEY_TYPE:
 282                         break;
 283                 case CKA_VALUE:
 284                         break;
 285                 case CKA_VALUE_LEN:
 286                         break;
 287                 case CKA_VALUE_BITS:
 288                         break;
 289                 default:
 290                         /* Second tier search */
 291                         switch (template[i].type) {
 292                         case CKA_ENCRYPT:
 293                                 break;
 294                         case CKA_DECRYPT:
 295                                 break;
 296                         case CKA_WRAP:
 297                                 break;
 298                         case CKA_UNWRAP:
 299                                 break;
 300                         case CKA_SIGN:
 301                                 break;
 302                         case CKA_SIGN_RECOVER:
 303                                 break;
 304                         case CKA_VERIFY:
 305                                 break;
 306                         case CKA_VERIFY_RECOVER:
 307                                 break;
 308                         case CKA_DERIVE:
 309                                 break;
 310                         default:
 311                                 /* Third tier search */
 312                                 rv = soft_lookup_attr(template[i].type);
 313                                 if (rv != CKR_OK)
 314                                         return (rv);
 315                                 break;
 316                         }
 317                         break;
 318                 }
 319         }
 320         return (rv);
 321 }
 322 
 323 static void
 324 cleanup_cert_attr(cert_attr_t *attr)
 325 {
 326         if (attr != NULL) {
 327                 freezero(attr->value, attr->length);
 328                 attr->value = NULL;
 329                 attr->length = 0;
 330         }
 331 }
 332 
 333 static CK_RV
 334 copy_cert_attr(cert_attr_t *src_attr, cert_attr_t **dest_attr)
 335 {
 336         CK_RV rv = CKR_OK;
 337 
 338         if (src_attr == NULL || dest_attr == NULL)
 339                 return (CKR_HOST_MEMORY);
 340 
 341         if (src_attr->value == NULL)
 342                 return (CKR_HOST_MEMORY);
 343 
 344         /* free memory if its already allocated */
 345         if (*dest_attr != NULL) {
 346                 cleanup_cert_attr(*dest_attr);
 347         } else {
 348                 *dest_attr = malloc(sizeof (cert_attr_t));
 349                 if (*dest_attr == NULL)
 350                         return (CKR_HOST_MEMORY);
 351         }
 352 
 353         (*dest_attr)->value = NULL;
 354         (*dest_attr)->length = 0;
 355 
 356         if (src_attr->length) {
 357                 (*dest_attr)->value = malloc(src_attr->length);
 358                 if ((*dest_attr)->value == NULL) {
 359                         free(*dest_attr);
 360                         return (CKR_HOST_MEMORY);
 361                 }
 362 
 363                 (void) memcpy((*dest_attr)->value, src_attr->value,
 364                     src_attr->length);
 365                 (*dest_attr)->length = src_attr->length;
 366         }
 367 
 368         return (rv);
 369 }
 370 
 371 void
 372 soft_cleanup_cert_object(soft_object_t *object_p)
 373 {
 374         CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
 375 
 376         if (object_p->class != CKO_CERTIFICATE ||
 377             OBJ_CERT(object_p) == NULL)
 378                 return;
 379 
 380         if (certtype == CKC_X_509) {
 381                 if (X509_CERT_SUBJECT(object_p) != NULL) {
 382                         cleanup_cert_attr(X509_CERT_SUBJECT(object_p));
 383                         free(X509_CERT_SUBJECT(object_p));
 384                         X509_CERT_SUBJECT(object_p) = NULL;
 385                 }
 386                 if (X509_CERT_VALUE(object_p) != NULL) {
 387                         cleanup_cert_attr(X509_CERT_VALUE(object_p));
 388                         free(X509_CERT_VALUE(object_p));
 389                         X509_CERT_VALUE(object_p) = NULL;
 390                 }
 391                 free(OBJ_CERT(object_p));
 392         } else if (certtype == CKC_X_509_ATTR_CERT) {
 393                 if (X509_ATTR_CERT_VALUE(object_p) != NULL) {
 394                         cleanup_cert_attr(X509_ATTR_CERT_VALUE(object_p));
 395                         free(X509_ATTR_CERT_VALUE(object_p));
 396                         X509_ATTR_CERT_VALUE(object_p) = NULL;
 397                 }
 398                 if (X509_ATTR_CERT_OWNER(object_p) != NULL) {
 399                         cleanup_cert_attr(X509_ATTR_CERT_OWNER(object_p));
 400                         free(X509_ATTR_CERT_OWNER(object_p));
 401                         X509_ATTR_CERT_OWNER(object_p) = NULL;
 402                 }
 403                 free(OBJ_CERT(object_p));
 404         }
 405 }
 406 
 407 /*
 408  * Clean up and release all the storage in the extra attribute list
 409  * of an object.
 410  */
 411 void
 412 soft_cleanup_extra_attr(soft_object_t *object_p)
 413 {
 414 
 415         CK_ATTRIBUTE_INFO_PTR extra_attr;
 416         CK_ATTRIBUTE_INFO_PTR tmp;
 417 
 418         extra_attr = object_p->extra_attrlistp;
 419         while (extra_attr) {
 420                 tmp = extra_attr->next;
 421                 if (extra_attr->attr.pValue != NULL) {
 422                         /*
 423                          * All extra attributes in the extra attribute
 424                          * list have pValue points to the value of the
 425                          * attribute (with simple byte array type).
 426                          * Free the storage for the value of the attribute.
 427                          */
 428                         freezero(extra_attr->attr.pValue,
 429                             extra_attr->attr.ulValueLen);
 430                 }
 431 
 432                 /* Free the storage for the attribute_info struct. */
 433                 free(extra_attr);
 434                 extra_attr = tmp;
 435         }
 436 
 437         object_p->extra_attrlistp = NULL;
 438 }
 439 
 440 
 441 /*
 442  * Create the attribute_info struct to hold the object's attribute,
 443  * and add it to the extra attribute list of an object.
 444  */
 445 CK_RV
 446 soft_add_extra_attr(CK_ATTRIBUTE_PTR template, soft_object_t *object_p)
 447 {
 448 
 449         CK_ATTRIBUTE_INFO_PTR attrp;
 450 
 451         /* Allocate the storage for the attribute_info struct. */
 452         attrp = calloc(1, sizeof (attribute_info_t));
 453         if (attrp == NULL) {
 454                 return (CKR_HOST_MEMORY);
 455         }
 456 
 457         /* Set up attribute_info struct. */
 458         attrp->attr.type = template->type;
 459         attrp->attr.ulValueLen = template->ulValueLen;
 460 
 461         if ((template->pValue != NULL) &&
 462             (template->ulValueLen > 0)) {
 463                 /* Allocate storage for the value of the attribute. */
 464                 attrp->attr.pValue = malloc(template->ulValueLen);
 465                 if (attrp->attr.pValue == NULL) {
 466                         free(attrp);
 467                         return (CKR_HOST_MEMORY);
 468                 }
 469 
 470                 (void) memcpy(attrp->attr.pValue, template->pValue,
 471                     template->ulValueLen);
 472         } else {
 473                 attrp->attr.pValue = NULL;
 474         }
 475 
 476         /* Insert the new attribute in front of extra attribute list. */
 477         if (object_p->extra_attrlistp == NULL) {
 478                 object_p->extra_attrlistp = attrp;
 479                 attrp->next = NULL;
 480         } else {
 481                 attrp->next = object_p->extra_attrlistp;
 482                 object_p->extra_attrlistp = attrp;
 483         }
 484 
 485         return (CKR_OK);
 486 }
 487 
 488 CK_RV
 489 soft_copy_certificate(certificate_obj_t *oldcert, certificate_obj_t **newcert,
 490                 CK_CERTIFICATE_TYPE type)
 491 {
 492         CK_RV rv = CKR_OK;
 493         certificate_obj_t       *cert;
 494         x509_cert_t             x509;
 495         x509_attr_cert_t        x509_attr;
 496 
 497         cert = calloc(1, sizeof (certificate_obj_t));
 498         if (cert == NULL) {
 499                 return (CKR_HOST_MEMORY);
 500         }
 501 
 502         if (type == CKC_X_509) {
 503                 x509 = oldcert->cert_type_u.x509;
 504                 if (x509.subject)
 505                         if ((rv = copy_cert_attr(x509.subject,
 506                             &cert->cert_type_u.x509.subject)))
 507                                 return (rv);
 508                 if (x509.value)
 509                         if ((rv = copy_cert_attr(x509.value,
 510                             &cert->cert_type_u.x509.value)))
 511                                 return (rv);
 512         } else if (type == CKC_X_509_ATTR_CERT) {
 513                 x509_attr = oldcert->cert_type_u.x509_attr;
 514                 if (x509_attr.owner)
 515                         if ((rv = copy_cert_attr(x509_attr.owner,
 516                             &cert->cert_type_u.x509_attr.owner)))
 517                                 return (rv);
 518                 if (x509_attr.value)
 519                         if ((rv = copy_cert_attr(x509_attr.value,
 520                             &cert->cert_type_u.x509_attr.value)))
 521                                 return (rv);
 522         } else {
 523                 /* wrong certificate type */
 524                 rv = CKR_ATTRIBUTE_TYPE_INVALID;
 525         }
 526         if (rv == CKR_OK)
 527                 *newcert = cert;
 528         return (rv);
 529 }
 530 
 531 /*
 532  * Copy the attribute_info struct from the old object to a new attribute_info
 533  * struct, and add that new struct to the extra attribute list of the new
 534  * object.
 535  */
 536 CK_RV
 537 soft_copy_extra_attr(CK_ATTRIBUTE_INFO_PTR old_attrp, soft_object_t *object_p)
 538 {
 539         CK_ATTRIBUTE_INFO_PTR attrp;
 540 
 541         /* Allocate attribute_info struct. */
 542         attrp = calloc(1, sizeof (attribute_info_t));
 543         if (attrp == NULL) {
 544                 return (CKR_HOST_MEMORY);
 545         }
 546 
 547         attrp->attr.type = old_attrp->attr.type;
 548         attrp->attr.ulValueLen = old_attrp->attr.ulValueLen;
 549 
 550         if ((old_attrp->attr.pValue != NULL) &&
 551             (old_attrp->attr.ulValueLen > 0)) {
 552                 attrp->attr.pValue = malloc(old_attrp->attr.ulValueLen);
 553                 if (attrp->attr.pValue == NULL) {
 554                         free(attrp);
 555                         return (CKR_HOST_MEMORY);
 556                 }
 557 
 558                 (void) memcpy(attrp->attr.pValue, old_attrp->attr.pValue,
 559                     old_attrp->attr.ulValueLen);
 560         } else {
 561                 attrp->attr.pValue = NULL;
 562         }
 563 
 564         /* Insert the new attribute in front of extra attribute list */
 565         if (object_p->extra_attrlistp == NULL) {
 566                 object_p->extra_attrlistp = attrp;
 567                 attrp->next = NULL;
 568         } else {
 569                 attrp->next = object_p->extra_attrlistp;
 570                 object_p->extra_attrlistp = attrp;
 571         }
 572 
 573         return (CKR_OK);
 574 }
 575 
 576 
 577 /*
 578  * Get the attribute triple from the extra attribute list in the object
 579  * (if the specified attribute type is found), and copy it to a template.
 580  * Note the type of the attribute to be copied is specified by the template,
 581  * and the storage is pre-allocated for the atrribute value in the template
 582  * for doing the copy.
 583  */
 584 CK_RV
 585 get_extra_attr_from_object(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
 586 {
 587 
 588         CK_ATTRIBUTE_INFO_PTR extra_attr;
 589         CK_ATTRIBUTE_TYPE type = template->type;
 590 
 591         extra_attr = object_p->extra_attrlistp;
 592 
 593         while (extra_attr) {
 594                 if (type == extra_attr->attr.type) {
 595                         /* Found it. */
 596                         break;
 597                 } else {
 598                         /* Does not match, try next one. */
 599                         extra_attr = extra_attr->next;
 600                 }
 601         }
 602 
 603         if (extra_attr == NULL) {
 604                 /* A valid but un-initialized attribute. */
 605                 template->ulValueLen = 0;
 606                 return (CKR_OK);
 607         }
 608 
 609         /*
 610          * We found the attribute in the extra attribute list.
 611          */
 612         if (template->pValue == NULL) {
 613                 template->ulValueLen = extra_attr->attr.ulValueLen;
 614                 return (CKR_OK);
 615         }
 616 
 617         if (template->ulValueLen >= extra_attr->attr.ulValueLen) {
 618                 /*
 619                  * The buffer provided by the application is large
 620                  * enough to hold the value of the attribute.
 621                  */
 622                 (void) memcpy(template->pValue, extra_attr->attr.pValue,
 623                     extra_attr->attr.ulValueLen);
 624                 template->ulValueLen = extra_attr->attr.ulValueLen;
 625                 return (CKR_OK);
 626         } else {
 627                 /*
 628                  * The buffer provided by the application does
 629                  * not have enough space to hold the value.
 630                  */
 631                 template->ulValueLen = (CK_ULONG)-1;
 632                 return (CKR_BUFFER_TOO_SMALL);
 633         }
 634 }
 635 
 636 
 637 /*
 638  * Modify the attribute triple in the extra attribute list of the object
 639  * if the specified attribute type is found. Otherwise, just add it to
 640  * list.
 641  */
 642 CK_RV
 643 set_extra_attr_to_object(soft_object_t *object_p, CK_ATTRIBUTE_TYPE type,
 644         CK_ATTRIBUTE_PTR template)
 645 {
 646 
 647         CK_ATTRIBUTE_INFO_PTR extra_attr;
 648 
 649         extra_attr = object_p->extra_attrlistp;
 650 
 651         while (extra_attr) {
 652                 if (type == extra_attr->attr.type) {
 653                         /* Found it. */
 654                         break;
 655                 } else {
 656                         /* Does not match, try next one. */
 657                         extra_attr = extra_attr->next;
 658                 }
 659         }
 660 
 661         if (extra_attr == NULL) {
 662                 /*
 663                  * This attribute is a new one, go ahead adding it to
 664                  * the extra attribute list.
 665                  */
 666                 return (soft_add_extra_attr(template, object_p));
 667         }
 668 
 669         /* We found the attribute in the extra attribute list. */
 670         if ((template->pValue != NULL) &&
 671             (template->ulValueLen > 0)) {
 672                 if (template->ulValueLen > extra_attr->attr.ulValueLen) {
 673                         /* The old buffer is too small to hold the new value. */
 674                         if (extra_attr->attr.pValue != NULL) {
 675                                 /* Free storage for the old attribute value. */
 676                                 freezero(extra_attr->attr.pValue,
 677                                     extra_attr->attr.ulValueLen);
 678                         }
 679 
 680                         /* Allocate storage for the new attribute value. */
 681                         extra_attr->attr.pValue = malloc(template->ulValueLen);
 682                         if (extra_attr->attr.pValue == NULL) {
 683                                 return (CKR_HOST_MEMORY);
 684                         }
 685                 }
 686 
 687                 /* Replace the attribute with new value. */
 688                 extra_attr->attr.ulValueLen = template->ulValueLen;
 689                 (void) memcpy(extra_attr->attr.pValue, template->pValue,
 690                     template->ulValueLen);
 691         } else {
 692                 extra_attr->attr.pValue = NULL;
 693         }
 694 
 695         return (CKR_OK);
 696 }
 697 
 698 
 699 /*
 700  * Copy the big integer attribute value from template to a biginteger_t struct.
 701  */
 702 CK_RV
 703 get_bigint_attr_from_template(biginteger_t *big, CK_ATTRIBUTE_PTR template)
 704 {
 705 
 706         if ((template->pValue != NULL) &&
 707             (template->ulValueLen > 0)) {
 708                 /* Allocate storage for the value of the attribute. */
 709                 big->big_value = malloc(template->ulValueLen);
 710                 if (big->big_value == NULL) {
 711                         return (CKR_HOST_MEMORY);
 712                 }
 713 
 714                 (void) memcpy(big->big_value, template->pValue,
 715                     template->ulValueLen);
 716                 big->big_value_len = template->ulValueLen;
 717         } else {
 718                 big->big_value = NULL;
 719                 big->big_value_len = 0;
 720         }
 721 
 722         return (CKR_OK);
 723 }
 724 
 725 
 726 /*
 727  * Copy the big integer attribute value from a biginteger_t struct in the
 728  * object to a template.
 729  */
 730 CK_RV
 731 get_bigint_attr_from_object(biginteger_t *big, CK_ATTRIBUTE_PTR template)
 732 {
 733 
 734         if (template->pValue == NULL) {
 735                 template->ulValueLen = big->big_value_len;
 736                 return (CKR_OK);
 737         }
 738 
 739         if (big->big_value == NULL) {
 740                 template->ulValueLen = 0;
 741                 return (CKR_OK);
 742         }
 743 
 744         if (template->ulValueLen >= big->big_value_len) {
 745                 /*
 746                  * The buffer provided by the application is large
 747                  * enough to hold the value of the attribute.
 748                  */
 749                 (void) memcpy(template->pValue, big->big_value,
 750                     big->big_value_len);
 751                 template->ulValueLen = big->big_value_len;
 752                 return (CKR_OK);
 753         } else {
 754                 /*
 755                  * The buffer provided by the application does
 756                  * not have enough space to hold the value.
 757                  */
 758                 template->ulValueLen = (CK_ULONG)-1;
 759                 return (CKR_BUFFER_TOO_SMALL);
 760         }
 761 }
 762 
 763 
 764 /*
 765  * Copy the boolean data type attribute value from an object for the
 766  * specified attribute to the template.
 767  */
 768 CK_RV
 769 get_bool_attr_from_object(soft_object_t *object_p, CK_ULONG bool_flag,
 770         CK_ATTRIBUTE_PTR template)
 771 {
 772 
 773         if (template->pValue == NULL) {
 774                 template->ulValueLen = sizeof (CK_BBOOL);
 775                 return (CKR_OK);
 776         }
 777 
 778         if (template->ulValueLen >= sizeof (CK_BBOOL)) {
 779                 /*
 780                  * The buffer provided by the application is large
 781                  * enough to hold the value of the attribute.
 782                  */
 783                 if (object_p->bool_attr_mask & bool_flag) {
 784                         *((CK_BBOOL *)template->pValue) = B_TRUE;
 785                 } else {
 786                         *((CK_BBOOL *)template->pValue) = B_FALSE;
 787                 }
 788 
 789                 template->ulValueLen = sizeof (CK_BBOOL);
 790                 return (CKR_OK);
 791         } else {
 792                 /*
 793                  * The buffer provided by the application does
 794                  * not have enough space to hold the value.
 795                  */
 796                 template->ulValueLen = (CK_ULONG)-1;
 797                 return (CKR_BUFFER_TOO_SMALL);
 798         }
 799 }
 800 
 801 /*
 802  * Set the boolean data type attribute value in the object.
 803  */
 804 CK_RV
 805 set_bool_attr_to_object(soft_object_t *object_p, CK_ULONG bool_flag,
 806         CK_ATTRIBUTE_PTR template)
 807 {
 808 
 809         if (*(CK_BBOOL *)template->pValue)
 810                 object_p->bool_attr_mask |= bool_flag;
 811         else
 812                 object_p->bool_attr_mask &= ~bool_flag;
 813 
 814         return (CKR_OK);
 815 }
 816 
 817 
 818 /*
 819  * Copy the CK_ULONG data type attribute value from an object to the
 820  * template.
 821  */
 822 CK_RV
 823 get_ulong_attr_from_object(CK_ULONG value, CK_ATTRIBUTE_PTR template)
 824 {
 825 
 826         if (template->pValue == NULL) {
 827                 template->ulValueLen = sizeof (CK_ULONG);
 828                 return (CKR_OK);
 829         }
 830 
 831         if (template->ulValueLen >= sizeof (CK_ULONG)) {
 832                 /*
 833                  * The buffer provided by the application is large
 834                  * enough to hold the value of the attribute.
 835                  * It is also assumed to be correctly aligned.
 836                  */
 837                 *(CK_ULONG_PTR)template->pValue = value;
 838                 template->ulValueLen = sizeof (CK_ULONG);
 839                 return (CKR_OK);
 840         } else {
 841                 /*
 842                  * The buffer provided by the application does
 843                  * not have enough space to hold the value.
 844                  */
 845                 template->ulValueLen = (CK_ULONG)-1;
 846                 return (CKR_BUFFER_TOO_SMALL);
 847         }
 848 }
 849 
 850 
 851 /*
 852  * Copy the CK_ULONG data type attribute value from a template to the
 853  * object.
 854  */
 855 static CK_RV
 856 get_ulong_attr_from_template(CK_ULONG *value, CK_ATTRIBUTE_PTR template)
 857 {
 858 
 859         if (template->ulValueLen < sizeof (CK_ULONG))
 860                 return (CKR_ATTRIBUTE_VALUE_INVALID);
 861 
 862         if (template->pValue != NULL) {
 863                 *value = *(CK_ULONG_PTR)template->pValue;
 864         } else {
 865                 *value = 0;
 866         }
 867 
 868         return (CKR_OK);
 869 }
 870 
 871 /*
 872  * Copy the big integer attribute value from source's biginteger_t to
 873  * destination's biginteger_t.
 874  */
 875 void
 876 copy_bigint_attr(biginteger_t *src, biginteger_t *dst)
 877 {
 878 
 879         if ((src->big_value != NULL) &&
 880             (src->big_value_len > 0)) {
 881                 /*
 882                  * To do the copy, just have dst's big_value points
 883                  * to src's.
 884                  */
 885                 dst->big_value = src->big_value;
 886                 dst->big_value_len = src->big_value_len;
 887 
 888                 /*
 889                  * After the copy, nullify the src's big_value pointer.
 890                  * It prevents any double freeing the value.
 891                  */
 892                 src->big_value = NULL;
 893                 src->big_value_len = 0;
 894         } else {
 895                 dst->big_value = NULL;
 896                 dst->big_value_len = 0;
 897         }
 898 }
 899 
 900 CK_RV
 901 get_string_from_template(CK_ATTRIBUTE_PTR dest, CK_ATTRIBUTE_PTR src)
 902 {
 903         if ((src->pValue != NULL) &&
 904             (src->ulValueLen > 0)) {
 905                 /* Allocate storage for the value of the attribute. */
 906                 dest->pValue = malloc(src->ulValueLen);
 907                 if (dest->pValue == NULL) {
 908                         return (CKR_HOST_MEMORY);
 909                 }
 910 
 911                 (void) memcpy(dest->pValue, src->pValue,
 912                     src->ulValueLen);
 913                 dest->ulValueLen = src->ulValueLen;
 914                 dest->type = src->type;
 915         } else {
 916                 dest->pValue = NULL;
 917                 dest->ulValueLen = 0;
 918                 dest->type = src->type;
 919         }
 920 
 921         return (CKR_OK);
 922 
 923 }
 924 
 925 CK_RV
 926 get_cert_attr_from_template(cert_attr_t **dest, CK_ATTRIBUTE_PTR src)
 927 {
 928         if (src->pValue != NULL && src->ulValueLen > 0) {
 929                 /*
 930                  * If the attribute was already set, clear out the
 931                  * existing value and release the memory.
 932                  */
 933                 if (*dest != NULL) {
 934                         cleanup_cert_attr(*dest);
 935                 } else {
 936                         *dest = malloc(sizeof (cert_attr_t));
 937                         if (*dest == NULL) {
 938                                 return (CKR_HOST_MEMORY);
 939                         }
 940                         (void) memset(*dest, 0, sizeof (cert_attr_t));
 941                 }
 942                 (*dest)->value = malloc(src->ulValueLen);
 943                 if ((*dest)->value == NULL) {
 944                         free(*dest);
 945                         *dest = NULL;
 946                         return (CKR_HOST_MEMORY);
 947                 }
 948                 (void) memcpy((*dest)->value, src->pValue, src->ulValueLen);
 949                 (*dest)->length = src->ulValueLen;
 950         }
 951 
 952         return (CKR_OK);
 953 }
 954 
 955 /*
 956  * Copy the certificate attribute information to the template.
 957  * If the template attribute is not big enough, set the ulValueLen=-1
 958  * and return CKR_BUFFER_TOO_SMALL.
 959  */
 960 static CK_RV
 961 get_cert_attr_from_object(cert_attr_t *src, CK_ATTRIBUTE_PTR template)
 962 {
 963         if (template->pValue == NULL) {
 964                 template->ulValueLen = src->length;
 965                 return (CKR_OK);
 966         } else if (template->ulValueLen >= src->length) {
 967                 /*
 968                  * The buffer provided by the application is large
 969                  * enough to hold the value of the attribute.
 970                  */
 971                 (void) memcpy(template->pValue, src->value, src->length);
 972                 template->ulValueLen = src->length;
 973                 return (CKR_OK);
 974         } else {
 975                 /*
 976                  * The buffer provided by the application does
 977                  * not have enough space to hold the value.
 978                  */
 979                 template->ulValueLen = (CK_ULONG)-1;
 980                 return (CKR_BUFFER_TOO_SMALL);
 981         }
 982 }
 983 
 984 void
 985 string_attr_cleanup(CK_ATTRIBUTE_PTR template)
 986 {
 987         freezero(template->pValue, template->ulValueLen);
 988         template->pValue = NULL;
 989         template->ulValueLen = 0;
 990 }
 991 
 992 /*
 993  * Release the storage allocated for object attribute with big integer
 994  * value.
 995  */
 996 void
 997 bigint_attr_cleanup(biginteger_t *big)
 998 {
 999 
1000         if (big == NULL)
1001                 return;
1002 
1003         freezero(big->big_value, big->big_value_len);
1004         big->big_value = NULL;
1005         big->big_value_len = 0;
1006 }
1007 
1008 
1009 /*
1010  * Clean up and release all the storage allocated to hold the big integer
1011  * attributes associated with the type (i.e. class) of the object. Also,
1012  * release the storage allocated to the type of the object.
1013  */
1014 void
1015 soft_cleanup_object_bigint_attrs(soft_object_t *object_p)
1016 {
1017 
1018         CK_OBJECT_CLASS class = object_p->class;
1019         CK_KEY_TYPE     keytype = object_p->key_type;
1020 
1021 
1022         switch (class) {
1023         case CKO_PUBLIC_KEY:
1024                 if (OBJ_PUB(object_p)) {
1025                         switch (keytype) {
1026                         case CKK_RSA:
1027                                 bigint_attr_cleanup(OBJ_PUB_RSA_MOD(
1028                                     object_p));
1029                                 bigint_attr_cleanup(OBJ_PUB_RSA_PUBEXPO(
1030                                     object_p));
1031                                 break;
1032 
1033                         case CKK_DSA:
1034                                 bigint_attr_cleanup(OBJ_PUB_DSA_PRIME(
1035                                     object_p));
1036                                 bigint_attr_cleanup(OBJ_PUB_DSA_SUBPRIME(
1037                                     object_p));
1038                                 bigint_attr_cleanup(OBJ_PUB_DSA_BASE(
1039                                     object_p));
1040                                 bigint_attr_cleanup(OBJ_PUB_DSA_VALUE(
1041                                     object_p));
1042                                 break;
1043 
1044                         case CKK_DH:
1045                                 bigint_attr_cleanup(OBJ_PUB_DH_PRIME(
1046                                     object_p));
1047                                 bigint_attr_cleanup(OBJ_PUB_DH_BASE(
1048                                     object_p));
1049                                 bigint_attr_cleanup(OBJ_PUB_DH_VALUE(
1050                                     object_p));
1051                                 break;
1052 
1053                         case CKK_X9_42_DH:
1054                                 bigint_attr_cleanup(OBJ_PUB_DH942_PRIME(
1055                                     object_p));
1056                                 bigint_attr_cleanup(OBJ_PUB_DH942_BASE(
1057                                     object_p));
1058                                 bigint_attr_cleanup(OBJ_PUB_DH942_SUBPRIME(
1059                                     object_p));
1060                                 bigint_attr_cleanup(OBJ_PUB_DH942_VALUE(
1061                                     object_p));
1062                                 break;
1063                         case CKK_EC:
1064                                 bigint_attr_cleanup(OBJ_PUB_EC_POINT(
1065                                     object_p));
1066                                 break;
1067                         }
1068 
1069                         /* Release Public Key Object struct */
1070                         free(OBJ_PUB(object_p));
1071                         OBJ_PUB(object_p) = NULL;
1072                 }
1073                 break;
1074 
1075         case CKO_PRIVATE_KEY:
1076                 if (OBJ_PRI(object_p)) {
1077                         switch (keytype) {
1078                         case CKK_RSA:
1079                                 bigint_attr_cleanup(OBJ_PRI_RSA_MOD(
1080                                     object_p));
1081                                 bigint_attr_cleanup(OBJ_PRI_RSA_PUBEXPO(
1082                                     object_p));
1083                                 bigint_attr_cleanup(OBJ_PRI_RSA_PRIEXPO(
1084                                     object_p));
1085                                 bigint_attr_cleanup(OBJ_PRI_RSA_PRIME1(
1086                                     object_p));
1087                                 bigint_attr_cleanup(OBJ_PRI_RSA_PRIME2(
1088                                     object_p));
1089                                 bigint_attr_cleanup(OBJ_PRI_RSA_EXPO1(
1090                                     object_p));
1091                                 bigint_attr_cleanup(OBJ_PRI_RSA_EXPO2(
1092                                     object_p));
1093                                 bigint_attr_cleanup(OBJ_PRI_RSA_COEF(
1094                                     object_p));
1095                                 break;
1096 
1097                         case CKK_DSA:
1098                                 bigint_attr_cleanup(OBJ_PRI_DSA_PRIME(
1099                                     object_p));
1100                                 bigint_attr_cleanup(OBJ_PRI_DSA_SUBPRIME(
1101                                     object_p));
1102                                 bigint_attr_cleanup(OBJ_PRI_DSA_BASE(
1103                                     object_p));
1104                                 bigint_attr_cleanup(OBJ_PRI_DSA_VALUE(
1105                                     object_p));
1106                                 break;
1107 
1108                         case CKK_DH:
1109                                 bigint_attr_cleanup(OBJ_PRI_DH_PRIME(
1110                                     object_p));
1111                                 bigint_attr_cleanup(OBJ_PRI_DH_BASE(
1112                                     object_p));
1113                                 bigint_attr_cleanup(OBJ_PRI_DH_VALUE(
1114                                     object_p));
1115                                 break;
1116 
1117                         case CKK_X9_42_DH:
1118                                 bigint_attr_cleanup(OBJ_PRI_DH942_PRIME(
1119                                     object_p));
1120                                 bigint_attr_cleanup(OBJ_PRI_DH942_BASE(
1121                                     object_p));
1122                                 bigint_attr_cleanup(OBJ_PRI_DH942_SUBPRIME(
1123                                     object_p));
1124                                 bigint_attr_cleanup(OBJ_PRI_DH942_VALUE(
1125                                     object_p));
1126                                 break;
1127 
1128                         case CKK_EC:
1129                                 bigint_attr_cleanup(OBJ_PRI_EC_VALUE(
1130                                     object_p));
1131                                 break;
1132                         }
1133 
1134                         /* Release Private Key Object struct. */
1135                         free(OBJ_PRI(object_p));
1136                         OBJ_PRI(object_p) = NULL;
1137                 }
1138                 break;
1139 
1140         case CKO_SECRET_KEY:
1141                 if (OBJ_SEC(object_p)) {
1142                         /* cleanup key data area */
1143                         if (OBJ_SEC_VALUE(object_p) != NULL &&
1144                             OBJ_SEC_VALUE_LEN(object_p) > 0) {
1145                                 freezero(OBJ_SEC_VALUE(object_p),
1146                                     OBJ_SEC_VALUE_LEN(object_p));
1147                         }
1148                         /* cleanup key schedule data area */
1149                         if (OBJ_KEY_SCHED(object_p) != NULL &&
1150                             OBJ_KEY_SCHED_LEN(object_p) > 0) {
1151                                 freezero(OBJ_KEY_SCHED(object_p),
1152                                     OBJ_KEY_SCHED_LEN(object_p));
1153                         }
1154 
1155                         /* Release Secret Key Object struct. */
1156                         free(OBJ_SEC(object_p));
1157                         OBJ_SEC(object_p) = NULL;
1158                 }
1159                 break;
1160 
1161         case CKO_DOMAIN_PARAMETERS:
1162                 if (OBJ_DOM(object_p)) {
1163                         switch (keytype) {
1164                         case CKK_DSA:
1165                                 bigint_attr_cleanup(OBJ_DOM_DSA_PRIME(
1166                                     object_p));
1167                                 bigint_attr_cleanup(OBJ_DOM_DSA_SUBPRIME(
1168                                     object_p));
1169                                 bigint_attr_cleanup(OBJ_DOM_DSA_BASE(
1170                                     object_p));
1171                                 break;
1172 
1173                         case CKK_DH:
1174                                 bigint_attr_cleanup(OBJ_DOM_DH_PRIME(
1175                                     object_p));
1176                                 bigint_attr_cleanup(OBJ_DOM_DH_BASE(
1177                                     object_p));
1178                                 break;
1179 
1180                         case CKK_X9_42_DH:
1181                                 bigint_attr_cleanup(OBJ_DOM_DH942_PRIME(
1182                                     object_p));
1183                                 bigint_attr_cleanup(OBJ_DOM_DH942_BASE(
1184                                     object_p));
1185                                 bigint_attr_cleanup(OBJ_DOM_DH942_SUBPRIME(
1186                                     object_p));
1187                                 break;
1188                         }
1189 
1190                         /* Release Domain Parameters Object struct. */
1191                         free(OBJ_DOM(object_p));
1192                         OBJ_DOM(object_p) = NULL;
1193                 }
1194                 break;
1195         }
1196 }
1197 
1198 
1199 /*
1200  * Parse the common attributes. Return to caller with appropriate return
1201  * value to indicate if the supplied template specifies a valid attribute
1202  * with a valid value.
1203  */
1204 CK_RV
1205 soft_parse_common_attrs(CK_ATTRIBUTE_PTR template, uchar_t *object_type)
1206 {
1207 
1208         CK_RV rv = CKR_OK;
1209 
1210         switch (template->type) {
1211         case CKA_CLASS:
1212                 break;
1213 
1214         /* default boolean attributes */
1215         case CKA_TOKEN:
1216                 if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1217                         if (!soft_keystore_status(KEYSTORE_INITIALIZED))
1218                                 return (CKR_DEVICE_REMOVED);
1219                         *object_type |= TOKEN_OBJECT;
1220                 }
1221                 break;
1222 
1223         case CKA_PRIVATE:
1224                 if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
1225                         (void) pthread_mutex_lock(&soft_giant_mutex);
1226                         if (!soft_slot.authenticated) {
1227                                 /*
1228                                  * Check if this is the special case when
1229                                  * the PIN is never initialized in the keystore.
1230                                  * If true, we will let it pass here and let
1231                                  * it fail with CKR_PIN_EXPIRED later on.
1232                                  */
1233                                 if (!soft_slot.userpin_change_needed) {
1234                                         (void) pthread_mutex_unlock(
1235                                             &soft_giant_mutex);
1236                                         return (CKR_USER_NOT_LOGGED_IN);
1237                                 }
1238                         }
1239                         (void) pthread_mutex_unlock(&soft_giant_mutex);
1240                         *object_type |= PRIVATE_OBJECT;
1241                 }
1242                 break;
1243 
1244         case CKA_LABEL:
1245                 break;
1246 
1247         default:
1248                 rv = CKR_TEMPLATE_INCONSISTENT;
1249         }
1250 
1251         return (rv);
1252 }
1253 
1254 
1255 /*
1256  * Build a Public Key Object.
1257  *
1258  * - Parse the object's template, and when an error is detected such as
1259  *   invalid attribute type, invalid attribute value, etc., return
1260  *   with appropriate return value.
1261  * - Set up attribute mask field in the object for the supplied common
1262  *   attributes that have boolean type.
1263  * - Build the attribute_info struct to hold the value of each supplied
1264  *   attribute that has byte array type. Link attribute_info structs
1265  *   together to form the extra attribute list of the object.
1266  * - Allocate storage for the Public Key object.
1267  * - Build the Public Key object according to the key type. Allocate
1268  *   storage to hold the big integer value for the supplied attributes
1269  *   that are required for a certain key type.
1270  *
1271  */
1272 CK_RV
1273 soft_build_public_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1274         soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1275 {
1276 
1277         ulong_t         i;
1278         CK_KEY_TYPE     keytype = (CK_KEY_TYPE)~0UL;
1279         uint64_t        attr_mask = PUBLIC_KEY_DEFAULT;
1280         CK_RV           rv = CKR_OK;
1281         int             isLabel = 0;
1282         /* Must set flags */
1283         int             isModulus = 0;
1284         int             isPubExpo = 0;
1285         int             isPrime = 0;
1286         int             isSubprime = 0;
1287         int             isBase = 0;
1288         int             isValue = 0;
1289         int             isECParam = 0;
1290         int             isECPoint = 0;
1291         /* Must not set flags */
1292         int             isModulusBits = 0;
1293         CK_ULONG        modulus_bits = 0;
1294 
1295         biginteger_t    modulus;
1296         biginteger_t    pubexpo;
1297         biginteger_t    prime;
1298         biginteger_t    subprime;
1299         biginteger_t    base;
1300         biginteger_t    value;
1301         biginteger_t    point;
1302         CK_ATTRIBUTE    string_tmp;
1303         CK_ATTRIBUTE    param_tmp;
1304 
1305         public_key_obj_t  *pbk;
1306         uchar_t object_type = 0;
1307 
1308         CK_ATTRIBUTE    defpubexpo = { CKA_PUBLIC_EXPONENT,
1309             (CK_BYTE_PTR)DEFAULT_PUB_EXPO, DEFAULT_PUB_EXPO_Len };
1310 
1311         BIGNUM          n;
1312 
1313         /* prevent bigint_attr_cleanup from freeing invalid attr value */
1314         (void) memset(&modulus, 0x0, sizeof (biginteger_t));
1315         (void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1316         (void) memset(&prime, 0x0, sizeof (biginteger_t));
1317         (void) memset(&subprime, 0x0, sizeof (biginteger_t));
1318         (void) memset(&base, 0x0, sizeof (biginteger_t));
1319         (void) memset(&value, 0x0, sizeof (biginteger_t));
1320         (void) memset(&point, 0x0, sizeof (biginteger_t));
1321         string_tmp.pValue = NULL;
1322         param_tmp.pValue = NULL;
1323 
1324         for (i = 0; i < ulAttrNum; i++) {
1325 
1326                 /* Public Key Object Attributes */
1327                 switch (template[i].type) {
1328 
1329                 /* common key attributes */
1330                 case CKA_KEY_TYPE:
1331                         keytype = *((CK_KEY_TYPE*)template[i].pValue);
1332                         break;
1333 
1334                 case CKA_ID:
1335                 case CKA_START_DATE:
1336                 case CKA_END_DATE:
1337 
1338                 /* common public key attribute */
1339                 case CKA_SUBJECT:
1340                         /*
1341                          * Allocate storage to hold the attribute
1342                          * value with byte array type, and add it to
1343                          * the extra attribute list of the object.
1344                          */
1345                         rv = soft_add_extra_attr(&template[i],
1346                             new_object);
1347                         if (rv != CKR_OK) {
1348                                 goto fail_cleanup;
1349                         }
1350                         break;
1351 
1352                 /*
1353                  * The following key related attribute types must
1354                  * not be specified by C_CreateObject, C_GenerateKey(Pair).
1355                  */
1356                 case CKA_LOCAL:
1357                 case CKA_KEY_GEN_MECHANISM:
1358                         rv = CKR_TEMPLATE_INCONSISTENT;
1359                         goto fail_cleanup;
1360 
1361                 /* Key related boolean attributes */
1362                 case CKA_DERIVE:
1363                         if (*(CK_BBOOL *)template[i].pValue)
1364                                 attr_mask |= DERIVE_BOOL_ON;
1365                         break;
1366 
1367                 case CKA_ENCRYPT:
1368                         if (*(CK_BBOOL *)template[i].pValue)
1369                                 attr_mask |= ENCRYPT_BOOL_ON;
1370                         else
1371                                 attr_mask &= ~ENCRYPT_BOOL_ON;
1372                         break;
1373 
1374                 case CKA_VERIFY:
1375                         if (*(CK_BBOOL *)template[i].pValue)
1376                                 attr_mask |= VERIFY_BOOL_ON;
1377                         else
1378                                 attr_mask &= ~VERIFY_BOOL_ON;
1379                         break;
1380 
1381                 case CKA_VERIFY_RECOVER:
1382                         if (*(CK_BBOOL *)template[i].pValue)
1383                                 attr_mask |= VERIFY_RECOVER_BOOL_ON;
1384                         else
1385                                 attr_mask &= ~VERIFY_RECOVER_BOOL_ON;
1386                         break;
1387 
1388                 case CKA_WRAP:
1389                         if (*(CK_BBOOL *)template[i].pValue)
1390                                 attr_mask |= WRAP_BOOL_ON;
1391                         else
1392                                 attr_mask &= ~WRAP_BOOL_ON;
1393                         break;
1394 
1395                 case CKA_TRUSTED:
1396                         if (*(CK_BBOOL *)template[i].pValue)
1397                                 attr_mask |= TRUSTED_BOOL_ON;
1398                         break;
1399 
1400                 case CKA_MODIFIABLE:
1401                         if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
1402                                 attr_mask |= NOT_MODIFIABLE_BOOL_ON;
1403                         break;
1404 
1405                 /*
1406                  * The following key related attribute types must
1407                  * be specified according to the key type by
1408                  * C_CreateObject.
1409                  */
1410                 case CKA_MODULUS:
1411 
1412                         isModulus = 1;
1413                         /*
1414                          * Copyin big integer attribute from template
1415                          * to a local variable.
1416                          */
1417                         rv = get_bigint_attr_from_template(&modulus,
1418                             &template[i]);
1419                         if (rv != CKR_OK)
1420                                 goto fail_cleanup;
1421 
1422                         /*
1423                          * Modulus length needs to be between min key length and
1424                          * max key length.
1425                          */
1426                         if ((modulus.big_value_len <
1427                             MIN_RSA_KEYLENGTH_IN_BYTES) ||
1428                             (modulus.big_value_len >
1429                             MAX_RSA_KEYLENGTH_IN_BYTES)) {
1430                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1431                                 goto fail_cleanup;
1432                         }
1433                         break;
1434 
1435                 case CKA_PUBLIC_EXPONENT:
1436                         isPubExpo = 1;
1437                         rv = get_bigint_attr_from_template(&pubexpo,
1438                             &template[i]);
1439                         if (rv != CKR_OK)
1440                                 goto fail_cleanup;
1441                         break;
1442 
1443                 case CKA_PRIME:
1444                         isPrime = 1;
1445                         rv = get_bigint_attr_from_template(&prime,
1446                             &template[i]);
1447                         if (rv != CKR_OK)
1448                                 goto fail_cleanup;
1449                         break;
1450 
1451                 case CKA_SUBPRIME:
1452                         isSubprime = 1;
1453                         rv = get_bigint_attr_from_template(&subprime,
1454                             &template[i]);
1455                         if (rv != CKR_OK)
1456                                 goto fail_cleanup;
1457                         break;
1458 
1459                 case CKA_BASE:
1460                         isBase = 1;
1461                         rv = get_bigint_attr_from_template(&base,
1462                             &template[i]);
1463                         if (rv != CKR_OK)
1464                                 goto fail_cleanup;
1465                         break;
1466 
1467                 case CKA_VALUE:
1468                         isValue = 1;
1469                         if (mode == SOFT_CREATE_OBJ) {
1470                                 if ((template[i].ulValueLen == 0) ||
1471                                     (template[i].pValue == NULL)) {
1472                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
1473                                         goto fail_cleanup;
1474                                 }
1475                         }
1476 
1477                         rv = get_bigint_attr_from_template(&value,
1478                             &template[i]);
1479                         if (rv != CKR_OK)
1480                                 goto fail_cleanup;
1481                         break;
1482 
1483                 case CKA_MODULUS_BITS:
1484                         isModulusBits = 1;
1485                         rv = get_ulong_attr_from_template(&modulus_bits,
1486                             &template[i]);
1487                         if (rv != CKR_OK)
1488                                 goto fail_cleanup;
1489                         break;
1490 
1491                 case CKA_LABEL:
1492                         isLabel = 1;
1493                         rv = get_string_from_template(&string_tmp,
1494                             &template[i]);
1495                         if (rv != CKR_OK)
1496                                 goto fail_cleanup;
1497                         break;
1498 
1499                 case CKA_EC_PARAMS:
1500                         isECParam = 1;
1501                         rv = get_string_from_template(&param_tmp, &template[i]);
1502                         if (rv != CKR_OK)
1503                                 goto fail_cleanup;
1504                         break;
1505 
1506                 case CKA_EC_POINT:
1507                         isECPoint = 1;
1508                         rv = get_bigint_attr_from_template(&point,
1509                             &template[i]);
1510                         if (rv != CKR_OK)
1511                                 goto fail_cleanup;
1512                         break;
1513 
1514                 default:
1515                         rv = soft_parse_common_attrs(&template[i],
1516                             &object_type);
1517                         if (rv != CKR_OK)
1518                                 goto fail_cleanup;
1519                         break;
1520                 }
1521         } /* For */
1522 
1523         /* Allocate storage for Public Key Object. */
1524         pbk = calloc(1, sizeof (public_key_obj_t));
1525         if (pbk == NULL) {
1526                 rv = CKR_HOST_MEMORY;
1527                 goto fail_cleanup;
1528         }
1529 
1530         new_object->object_class_u.public_key = pbk;
1531         new_object->class = CKO_PUBLIC_KEY;
1532 
1533         if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
1534                 rv = CKR_TEMPLATE_INCOMPLETE;
1535                 goto fail_cleanup;
1536         }
1537 
1538         if ((mode == SOFT_GEN_KEY) && (keytype == (CK_KEY_TYPE)~0UL)) {
1539                 keytype = key_type;
1540         }
1541 
1542         if ((mode == SOFT_GEN_KEY) && (keytype != key_type)) {
1543                 /*
1544                  * The key type specified in the template does not
1545                  * match the implied key type based on the mechanism.
1546                  */
1547                 rv = CKR_TEMPLATE_INCONSISTENT;
1548                 goto fail_cleanup;
1549         }
1550 
1551         new_object->key_type = keytype;
1552 
1553         /* Supported key types of the Public Key Object */
1554         switch (keytype) {
1555 
1556         case CKK_RSA:
1557                 if (mode == SOFT_CREATE_OBJ) {
1558                         if (isModulusBits || isPrime || isSubprime ||
1559                             isBase || isValue) {
1560                                 rv = CKR_TEMPLATE_INCONSISTENT;
1561                                 goto fail_cleanup;
1562                         }
1563 
1564                         if (isModulus && isPubExpo) {
1565                                 /*
1566                                  * Derive modulus_bits attribute from modulus.
1567                                  * Save modulus_bits integer value to the
1568                                  * designated place in the public key object.
1569                                  */
1570                                 n.malloced = 0;
1571 #ifdef  __sparcv9
1572                                 if (big_init(&n, (int)CHARLEN2BIGNUMLEN(
1573                                     modulus.big_value_len)) != BIG_OK) {
1574 #else   /* !__sparcv9 */
1575                                 if (big_init(&n, CHARLEN2BIGNUMLEN(
1576                                     modulus.big_value_len)) != BIG_OK) {
1577 #endif  /* __sparcv9 */
1578                                         rv = CKR_HOST_MEMORY;
1579                                         big_finish(&n);
1580                                         goto fail_cleanup;
1581                                 }
1582                                 bytestring2bignum(&n, modulus.big_value,
1583                                     modulus.big_value_len);
1584 
1585                                 modulus_bits = big_bitlength(&n);
1586                                 KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1587                                 big_finish(&n);
1588 
1589                                 /*
1590                                  * After modulus_bits has been computed,
1591                                  * it is safe to move modulus and pubexpo
1592                                  * big integer attribute value to the
1593                                  * designated place in the public key object.
1594                                  */
1595                                 copy_bigint_attr(&modulus,
1596                                     KEY_PUB_RSA_MOD(pbk));
1597 
1598                                 copy_bigint_attr(&pubexpo,
1599                                     KEY_PUB_RSA_PUBEXPO(pbk));
1600                         } else {
1601                                 rv = CKR_TEMPLATE_INCOMPLETE;
1602                                 goto fail_cleanup;
1603                         }
1604                 } else {
1605                         /* mode is SOFT_GEN_KEY */
1606 
1607                         if (isModulus || isPrime || isSubprime ||
1608                             isBase || isValue) {
1609                                 rv = CKR_TEMPLATE_INCONSISTENT;
1610                                 goto fail_cleanup;
1611                         }
1612 
1613 
1614                         if (isModulusBits) {
1615                                 /*
1616                                  * Copy big integer attribute value to the
1617                                  * designated place in the public key object.
1618                                  */
1619                                 KEY_PUB_RSA_MOD_BITS(pbk) = modulus_bits;
1620                         } else {
1621                                 rv = CKR_TEMPLATE_INCOMPLETE;
1622                                 goto fail_cleanup;
1623                         }
1624 
1625                         /*
1626                          * Use PKCS#11 default 0x010001 for public exponent
1627                          * if not not specified in attribute template.
1628                          */
1629                         if (!isPubExpo) {
1630                                 isPubExpo = 1;
1631                                 rv = get_bigint_attr_from_template(&pubexpo,
1632                                     &defpubexpo);
1633                                 if (rv != CKR_OK)
1634                                         goto fail_cleanup;
1635                         }
1636                         /*
1637                          * Copy big integer attribute value to the
1638                          * designated place in the public key object.
1639                          */
1640                         copy_bigint_attr(&pubexpo, KEY_PUB_RSA_PUBEXPO(pbk));
1641                 }
1642 
1643                 break;
1644 
1645         case CKK_DSA:
1646                 if (mode == SOFT_CREATE_OBJ) {
1647                         if (isModulusBits || isModulus || isPubExpo) {
1648                                 rv = CKR_TEMPLATE_INCONSISTENT;
1649                                 goto fail_cleanup;
1650                         }
1651 
1652                         if (isPrime && isSubprime && isBase && isValue) {
1653                                 copy_bigint_attr(&value,
1654                                     KEY_PUB_DSA_VALUE(pbk));
1655                         } else {
1656                                 rv = CKR_TEMPLATE_INCOMPLETE;
1657                                 goto fail_cleanup;
1658                         }
1659                 } else {
1660                         if (isModulusBits || isModulus || isPubExpo ||
1661                             isValue) {
1662                                 rv = CKR_TEMPLATE_INCONSISTENT;
1663                                 goto fail_cleanup;
1664                         }
1665 
1666                         if (!(isPrime && isSubprime && isBase)) {
1667                                 rv = CKR_TEMPLATE_INCOMPLETE;
1668                                 goto fail_cleanup;
1669                         }
1670                 }
1671 
1672                 copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk));
1673 
1674                 copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk));
1675 
1676                 copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk));
1677 
1678                 break;
1679 
1680         case CKK_DH:
1681                 if (mode == SOFT_CREATE_OBJ) {
1682                         if (isModulusBits || isModulus || isPubExpo ||
1683                             isSubprime) {
1684                                 rv = CKR_TEMPLATE_INCONSISTENT;
1685                                 goto fail_cleanup;
1686                         }
1687 
1688                         if (isPrime && isBase && isValue) {
1689                                 copy_bigint_attr(&value,
1690                                     KEY_PUB_DH_VALUE(pbk));
1691                         } else {
1692                                 rv = CKR_TEMPLATE_INCOMPLETE;
1693                                 goto fail_cleanup;
1694                         }
1695                 } else {
1696                         if (isModulusBits || isModulus || isPubExpo ||
1697                             isSubprime || isValue) {
1698                                 rv = CKR_TEMPLATE_INCONSISTENT;
1699                                 goto fail_cleanup;
1700                         }
1701 
1702                         if (!(isPrime && isBase)) {
1703                                 rv = CKR_TEMPLATE_INCOMPLETE;
1704                                 goto fail_cleanup;
1705                         }
1706                 }
1707 
1708                 copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk));
1709 
1710                 copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk));
1711 
1712                 break;
1713 
1714         case CKK_X9_42_DH:
1715                 if (mode == SOFT_CREATE_OBJ) {
1716                         if (isModulusBits || isModulus || isPubExpo) {
1717                                 rv = CKR_TEMPLATE_INCONSISTENT;
1718                                 goto fail_cleanup;
1719                         }
1720 
1721                         if (isPrime && isSubprime && isBase && isValue) {
1722                                 copy_bigint_attr(&value,
1723                                     KEY_PUB_DH942_VALUE(pbk));
1724                         } else {
1725                                 rv = CKR_TEMPLATE_INCOMPLETE;
1726                                 goto fail_cleanup;
1727                         }
1728                 } else {
1729                         if (isModulusBits || isModulus || isPubExpo ||
1730                             isValue) {
1731                                 rv = CKR_TEMPLATE_INCONSISTENT;
1732                                 goto fail_cleanup;
1733                         }
1734 
1735                         if (!(isPrime && isSubprime && isBase)) {
1736                                 rv = CKR_TEMPLATE_INCOMPLETE;
1737                                 goto fail_cleanup;
1738                         }
1739                 }
1740 
1741                 copy_bigint_attr(&prime, KEY_PUB_DH942_PRIME(pbk));
1742 
1743                 copy_bigint_attr(&base, KEY_PUB_DH942_BASE(pbk));
1744 
1745                 copy_bigint_attr(&subprime, KEY_PUB_DH942_SUBPRIME(pbk));
1746 
1747                 break;
1748 
1749         case CKK_EC:
1750                 if (mode == SOFT_CREATE_OBJ) {
1751                         if (isModulusBits || isModulus || isPubExpo ||
1752                             isPrime || isSubprime || isBase || isValue) {
1753                                 rv = CKR_TEMPLATE_INCONSISTENT;
1754                                 goto fail_cleanup;
1755 
1756                         } else if (!isECParam || !isECPoint) {
1757                                 rv = CKR_TEMPLATE_INCOMPLETE;
1758                                 goto fail_cleanup;
1759                         }
1760                 } else {
1761                         if (isModulusBits || isModulus || isPubExpo ||
1762                             isPrime || isSubprime || isBase || isValue) {
1763                                 rv = CKR_TEMPLATE_INCONSISTENT;
1764                                 goto fail_cleanup;
1765 
1766                         } else if (!isECParam) {
1767                                 rv = CKR_TEMPLATE_INCOMPLETE;
1768                                 goto fail_cleanup;
1769                         }
1770                 }
1771 
1772                 if (isECPoint) {
1773                         copy_bigint_attr(&point, KEY_PUB_EC_POINT(pbk));
1774                 }
1775                 rv = soft_add_extra_attr(&param_tmp, new_object);
1776                 if (rv != CKR_OK)
1777                         goto fail_cleanup;
1778                 string_attr_cleanup(&param_tmp);
1779                 break;
1780 
1781         default:
1782                 rv = CKR_TEMPLATE_INCONSISTENT;
1783                 goto fail_cleanup;
1784         }
1785 
1786         /* Set up object. */
1787         new_object->object_type = object_type;
1788         new_object->bool_attr_mask = attr_mask;
1789         if (isLabel) {
1790                 rv = soft_add_extra_attr(&string_tmp, new_object);
1791                 if (rv != CKR_OK)
1792                         goto fail_cleanup;
1793                 string_attr_cleanup(&string_tmp);
1794         }
1795 
1796         return (rv);
1797 
1798 fail_cleanup:
1799         /*
1800          * cleanup the storage allocated to the local variables.
1801          */
1802         bigint_attr_cleanup(&modulus);
1803         bigint_attr_cleanup(&pubexpo);
1804         bigint_attr_cleanup(&prime);
1805         bigint_attr_cleanup(&subprime);
1806         bigint_attr_cleanup(&base);
1807         bigint_attr_cleanup(&value);
1808         bigint_attr_cleanup(&point);
1809         string_attr_cleanup(&string_tmp);
1810         string_attr_cleanup(&param_tmp);
1811 
1812         /*
1813          * cleanup the storage allocated inside the object itself.
1814          */
1815         soft_cleanup_object(new_object);
1816 
1817         return (rv);
1818 }
1819 
1820 
1821 /*
1822  * Build a Private Key Object.
1823  *
1824  * - Parse the object's template, and when an error is detected such as
1825  *   invalid attribute type, invalid attribute value, etc., return
1826  *   with appropriate return value.
1827  * - Set up attribute mask field in the object for the supplied common
1828  *   attributes that have boolean type.
1829  * - Build the attribute_info struct to hold the value of each supplied
1830  *   attribute that has byte array type. Link attribute_info structs
1831  *   together to form the extra attribute list of the object.
1832  * - Allocate storage for the Private Key object.
1833  * - Build the Private Key object according to the key type. Allocate
1834  *   storage to hold the big integer value for the supplied attributes
1835  *   that are required for a certain key type.
1836  *
1837  */
1838 CK_RV
1839 soft_build_private_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
1840         soft_object_t *new_object, CK_ULONG mode, CK_KEY_TYPE key_type)
1841 {
1842         ulong_t         i;
1843         CK_KEY_TYPE     keytype = (CK_KEY_TYPE)~0UL;
1844         uint64_t        attr_mask = PRIVATE_KEY_DEFAULT;
1845         CK_RV           rv = CKR_OK;
1846         int             isLabel = 0;
1847         int             isECParam = 0;
1848         /* Must set flags unless mode == SOFT_UNWRAP_KEY */
1849         int             isModulus = 0;
1850         int             isPriExpo = 0;
1851         int             isPrime = 0;
1852         int             isSubprime = 0;
1853         int             isBase = 0;
1854         /* Must set flags if mode == SOFT_GEN_KEY */
1855         int             isValue = 0;
1856         /* Must not set flags */
1857         int             isValueBits = 0;
1858         CK_ULONG        value_bits = 0;
1859 
1860         /* Private Key RSA optional */
1861         int             isPubExpo = 0;
1862         int             isPrime1 = 0;
1863         int             isPrime2 = 0;
1864         int             isExpo1 = 0;
1865         int             isExpo2 = 0;
1866         int             isCoef = 0;
1867 
1868         biginteger_t    modulus;
1869         biginteger_t    priexpo;
1870         biginteger_t    prime;
1871         biginteger_t    subprime;
1872         biginteger_t    base;
1873         biginteger_t    value;
1874 
1875         biginteger_t    pubexpo;
1876         biginteger_t    prime1;
1877         biginteger_t    prime2;
1878         biginteger_t    expo1;
1879         biginteger_t    expo2;
1880         biginteger_t    coef;
1881         CK_ATTRIBUTE    string_tmp;
1882         CK_ATTRIBUTE    param_tmp;
1883         BIGNUM  x, q;
1884 
1885         private_key_obj_t *pvk;
1886         uchar_t object_type = 0;
1887 
1888         /* prevent bigint_attr_cleanup from freeing invalid attr value */
1889         (void) memset(&modulus, 0x0, sizeof (biginteger_t));
1890         (void) memset(&priexpo, 0x0, sizeof (biginteger_t));
1891         (void) memset(&prime, 0x0, sizeof (biginteger_t));
1892         (void) memset(&subprime, 0x0, sizeof (biginteger_t));
1893         (void) memset(&base, 0x0, sizeof (biginteger_t));
1894         (void) memset(&value, 0x0, sizeof (biginteger_t));
1895         (void) memset(&pubexpo, 0x0, sizeof (biginteger_t));
1896         (void) memset(&prime1, 0x0, sizeof (biginteger_t));
1897         (void) memset(&prime2, 0x0, sizeof (biginteger_t));
1898         (void) memset(&expo1, 0x0, sizeof (biginteger_t));
1899         (void) memset(&expo2, 0x0, sizeof (biginteger_t));
1900         (void) memset(&coef, 0x0, sizeof (biginteger_t));
1901         string_tmp.pValue = NULL;
1902         param_tmp.pValue = NULL;
1903         x.malloced = 0;
1904         q.malloced = 0;
1905 
1906         for (i = 0; i < ulAttrNum; i++) {
1907 
1908                 /* Private Key Object Attributes */
1909                 switch (template[i].type) {
1910                 /* common key attributes */
1911                 case CKA_KEY_TYPE:
1912                         keytype = *((CK_KEY_TYPE*)template[i].pValue);
1913                         break;
1914 
1915                 case CKA_ID:
1916                 case CKA_START_DATE:
1917                 case CKA_END_DATE:
1918 
1919                 /* common private key attribute */
1920                 case CKA_SUBJECT:
1921                         /*
1922                          * Allocate storage to hold the attribute
1923                          * value with byte array type, and add it to
1924                          * the extra attribute list of the object.
1925                          */
1926                         rv = soft_add_extra_attr(&template[i],
1927                             new_object);
1928                         if (rv != CKR_OK) {
1929                                 goto fail_cleanup;
1930                         }
1931                         break;
1932 
1933                 /*
1934                  * The following key related attribute types must
1935                  * not be specified by C_CreateObject or C_GenerateKey(Pair).
1936                  */
1937                 case CKA_LOCAL:
1938                 case CKA_KEY_GEN_MECHANISM:
1939                 case CKA_AUTH_PIN_FLAGS:
1940                 case CKA_ALWAYS_SENSITIVE:
1941                 case CKA_NEVER_EXTRACTABLE:
1942                         rv = CKR_TEMPLATE_INCONSISTENT;
1943                         goto fail_cleanup;
1944 
1945                 /* Key related boolean attributes */
1946                 case CKA_DERIVE:
1947                         if (*(CK_BBOOL *)template[i].pValue)
1948                                 attr_mask |= DERIVE_BOOL_ON;
1949                         break;
1950 
1951                 case CKA_SENSITIVE:
1952                         if (*(CK_BBOOL *)template[i].pValue)
1953                                 attr_mask |= SENSITIVE_BOOL_ON;
1954                         break;
1955 
1956                 case CKA_SECONDARY_AUTH:
1957                         if (*(CK_BBOOL *)template[i].pValue) {
1958                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
1959                                 goto fail_cleanup;
1960                         }
1961                         break;
1962 
1963                 case CKA_DECRYPT:
1964                         if (*(CK_BBOOL *)template[i].pValue)
1965                                 attr_mask |= DECRYPT_BOOL_ON;
1966                         else
1967                                 attr_mask &= ~DECRYPT_BOOL_ON;
1968                         break;
1969 
1970                 case CKA_SIGN:
1971                         if (*(CK_BBOOL *)template[i].pValue)
1972                                 attr_mask |= SIGN_BOOL_ON;
1973                         else
1974                                 attr_mask &= ~SIGN_BOOL_ON;
1975                         break;
1976 
1977                 case CKA_SIGN_RECOVER:
1978                         if (*(CK_BBOOL *)template[i].pValue)
1979                                 attr_mask |= SIGN_RECOVER_BOOL_ON;
1980                         else
1981                                 attr_mask &= ~SIGN_RECOVER_BOOL_ON;
1982                         break;
1983 
1984                 case CKA_UNWRAP:
1985                         if (*(CK_BBOOL *)template[i].pValue)
1986                                 attr_mask |= UNWRAP_BOOL_ON;
1987                         else
1988                                 attr_mask &= ~UNWRAP_BOOL_ON;
1989                         break;
1990 
1991                 case CKA_EXTRACTABLE:
1992                         if (*(CK_BBOOL *)template[i].pValue)
1993                                 attr_mask |= EXTRACTABLE_BOOL_ON;
1994                         else
1995                                 attr_mask &= ~EXTRACTABLE_BOOL_ON;
1996                         break;
1997 
1998                 case CKA_MODIFIABLE:
1999                         if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
2000                                 attr_mask |= NOT_MODIFIABLE_BOOL_ON;
2001                         break;
2002 
2003                 /*
2004                  * The following key related attribute types must
2005                  * be specified according to the key type by
2006                  * C_CreateObject.
2007                  */
2008                 case CKA_MODULUS:
2009 
2010                         isModulus = 1;
2011                         /*
2012                          * Copyin big integer attribute from template
2013                          * to a local variable.
2014                          */
2015                         rv = get_bigint_attr_from_template(&modulus,
2016                             &template[i]);
2017                         if (rv != CKR_OK)
2018                                 goto fail_cleanup;
2019 
2020                         /*
2021                          * Modulus length needs to be between min key length and
2022                          * max key length.
2023                          */
2024                         if ((modulus.big_value_len <
2025                             MIN_RSA_KEYLENGTH_IN_BYTES) ||
2026                             (modulus.big_value_len >
2027                             MAX_RSA_KEYLENGTH_IN_BYTES)) {
2028                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2029                                 goto fail_cleanup;
2030                         }
2031                         break;
2032 
2033                 case CKA_PUBLIC_EXPONENT:
2034 
2035                         isPubExpo = 1;
2036                         rv = get_bigint_attr_from_template(&pubexpo,
2037                             &template[i]);
2038                         if (rv != CKR_OK)
2039                                 goto fail_cleanup;
2040                         break;
2041 
2042                 case CKA_PRIVATE_EXPONENT:
2043 
2044                         isPriExpo = 1;
2045                         rv = get_bigint_attr_from_template(&priexpo,
2046                             &template[i]);
2047                         if (rv != CKR_OK)
2048                                 goto fail_cleanup;
2049                         break;
2050 
2051                 case CKA_PRIME_1:
2052                         isPrime1 = 1;
2053                         rv = get_bigint_attr_from_template(&prime1,
2054                             &template[i]);
2055                         if (rv != CKR_OK)
2056                                 goto fail_cleanup;
2057                         break;
2058 
2059                 case CKA_PRIME_2:
2060                         isPrime2 = 1;
2061                         rv = get_bigint_attr_from_template(&prime2,
2062                             &template[i]);
2063                         if (rv != CKR_OK)
2064                                 goto fail_cleanup;
2065                         break;
2066 
2067                 case CKA_EXPONENT_1:
2068                         isExpo1 = 1;
2069                         rv = get_bigint_attr_from_template(&expo1,
2070                             &template[i]);
2071                         if (rv != CKR_OK)
2072                                 goto fail_cleanup;
2073                         break;
2074 
2075                 case CKA_EXPONENT_2:
2076                         isExpo2 = 1;
2077                         rv = get_bigint_attr_from_template(&expo2,
2078                             &template[i]);
2079                         if (rv != CKR_OK)
2080                                 goto fail_cleanup;
2081                         break;
2082 
2083                 case CKA_COEFFICIENT:
2084                         isCoef = 1;
2085                         rv = get_bigint_attr_from_template(&coef,
2086                             &template[i]);
2087                         if (rv != CKR_OK)
2088                                 goto fail_cleanup;
2089                         break;
2090 
2091                 case CKA_PRIME:
2092                         isPrime = 1;
2093                         rv = get_bigint_attr_from_template(&prime,
2094                             &template[i]);
2095                         if (rv != CKR_OK)
2096                                 goto fail_cleanup;
2097                         break;
2098 
2099                 case CKA_SUBPRIME:
2100                         isSubprime = 1;
2101                         rv = get_bigint_attr_from_template(&subprime,
2102                             &template[i]);
2103                         if (rv != CKR_OK)
2104                                 goto fail_cleanup;
2105                         break;
2106 
2107                 case CKA_BASE:
2108                         isBase = 1;
2109                         rv = get_bigint_attr_from_template(&base,
2110                             &template[i]);
2111                         if (rv != CKR_OK)
2112                                 goto fail_cleanup;
2113                         break;
2114 
2115                 case CKA_VALUE:
2116                         isValue = 1;
2117                         if (mode == SOFT_CREATE_OBJ) {
2118                                 if ((template[i].ulValueLen == 0) ||
2119                                     (template[i].pValue == NULL)) {
2120                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
2121                                         goto fail_cleanup;
2122                                 }
2123                         }
2124 
2125                         rv = get_bigint_attr_from_template(&value,
2126                             &template[i]);
2127                         if (rv != CKR_OK)
2128                                 goto fail_cleanup;
2129                         break;
2130 
2131                 case CKA_VALUE_BITS:
2132                         isValueBits = 1;
2133                         rv = get_ulong_attr_from_template(&value_bits,
2134                             &template[i]);
2135                         if (rv != CKR_OK)
2136                                 goto fail_cleanup;
2137                         break;
2138 
2139                 case CKA_LABEL:
2140                         isLabel = 1;
2141                         rv = get_string_from_template(&string_tmp,
2142                             &template[i]);
2143                         if (rv != CKR_OK)
2144                                 goto fail_cleanup;
2145                         break;
2146 
2147                 case CKA_EC_PARAMS:
2148                         isECParam = 1;
2149                         rv = get_string_from_template(&param_tmp,
2150                             &template[i]);
2151                         if (rv != CKR_OK)
2152                                 goto fail_cleanup;
2153                         break;
2154 
2155                 default:
2156                         rv = soft_parse_common_attrs(&template[i],
2157                             &object_type);
2158                         if (rv != CKR_OK)
2159                                 goto fail_cleanup;
2160                         break;
2161 
2162                 }
2163         } /* For */
2164 
2165         /* Allocate storage for Private Key Object. */
2166         pvk = calloc(1, sizeof (private_key_obj_t));
2167         if (pvk == NULL) {
2168                 rv = CKR_HOST_MEMORY;
2169                 goto fail_cleanup;
2170         }
2171 
2172         new_object->object_class_u.private_key = pvk;
2173         new_object->class = CKO_PRIVATE_KEY;
2174 
2175         if ((mode == SOFT_CREATE_OBJ) && (keytype == (CK_KEY_TYPE)~0UL)) {
2176                 rv = CKR_TEMPLATE_INCOMPLETE;
2177                 goto fail_cleanup;
2178         }
2179 
2180         if (mode == SOFT_GEN_KEY) {
2181                 /*
2182                  * The key type is not specified in the application's
2183                  * template, so we use the implied key type based on
2184                  * the mechanism.
2185                  */
2186                 if (keytype == (CK_KEY_TYPE)~0UL) {
2187                         keytype = key_type;
2188                 }
2189 
2190                 /* If still unspecified, template is incomplete */
2191                 if (keytype == (CK_KEY_TYPE)~0UL) {
2192                         rv = CKR_TEMPLATE_INCOMPLETE;
2193                         goto fail_cleanup;
2194                 }
2195 
2196                 /*
2197                  * The key type specified in the template does not
2198                  * match the implied key type based on the mechanism.
2199                  */
2200                 if (keytype != key_type) {
2201                         rv = CKR_TEMPLATE_INCONSISTENT;
2202                         goto fail_cleanup;
2203                 }
2204         }
2205 
2206         if (mode == SOFT_UNWRAP_KEY) {
2207                 /*
2208                  * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2209                  * implied by the mechanism (key_type), so if it is not
2210                  * specified from the attribute template (keytype), it is
2211                  * incomplete.
2212                  */
2213                 if (keytype == (CK_KEY_TYPE)~0UL) {
2214                         rv = CKR_TEMPLATE_INCOMPLETE;
2215                         goto fail_cleanup;
2216                 }
2217         }
2218 
2219         new_object->key_type = keytype;
2220 
2221         /* Supported key types of the Private Key Object */
2222         switch (keytype) {
2223         case CKK_RSA:
2224                 if (isPrime || isSubprime || isBase || isValue ||
2225                     isValueBits) {
2226                         rv = CKR_TEMPLATE_INCONSISTENT;
2227                         goto fail_cleanup;
2228                 }
2229 
2230                 if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2231                         if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2232                             isPrime2 || isExpo1 || isExpo2 || isCoef) {
2233                                 rv = CKR_TEMPLATE_INCONSISTENT;
2234                                 goto fail_cleanup;
2235                         } else
2236                                 break;
2237                 }
2238 
2239                 if (isModulus && isPriExpo) {
2240                         /*
2241                          * Copy big integer attribute value to the
2242                          * designated place in the Private Key object.
2243                          */
2244                         copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk));
2245 
2246                         copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk));
2247                 } else {
2248                         rv = CKR_TEMPLATE_INCOMPLETE;
2249                         goto fail_cleanup;
2250                 }
2251 
2252                 /* The following attributes are optional. */
2253                 if (isPubExpo) {
2254                         copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk));
2255                 }
2256 
2257                 if (isPrime1) {
2258                         copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk));
2259                 }
2260 
2261                 if (isPrime2) {
2262                         copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk));
2263                 }
2264 
2265                 if (isExpo1) {
2266                         copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk));
2267                 }
2268 
2269                 if (isExpo2) {
2270                         copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk));
2271                 }
2272 
2273                 if (isCoef) {
2274                         copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk));
2275                 }
2276                 break;
2277 
2278         case CKK_DSA:
2279                 if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2280                     isPrime2 || isExpo1 || isExpo2 || isCoef ||
2281                     isValueBits) {
2282                         rv = CKR_TEMPLATE_INCONSISTENT;
2283                         goto fail_cleanup;
2284                 }
2285 
2286                 if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2287                         if (isPrime || isSubprime || isBase || isValue) {
2288                                 rv = CKR_TEMPLATE_INCONSISTENT;
2289                                 goto fail_cleanup;
2290                         } else
2291                                 break;
2292                 }
2293 
2294                 if (isPrime && isSubprime && isBase && isValue) {
2295                         /*
2296                          * The private value x must be less than subprime q.
2297                          * Size for big_init is in BIG_CHUNK_TYPE words.
2298                          */
2299 #ifdef  __sparcv9
2300                         if (big_init(&x,
2301                             (int)CHARLEN2BIGNUMLEN(value.big_value_len))
2302                             != BIG_OK) {
2303 #else   /* !__sparcv9 */
2304                         if (big_init(&x,
2305                             CHARLEN2BIGNUMLEN(value.big_value_len))
2306                             != BIG_OK) {
2307 #endif  /* __sparcv9 */
2308                                 rv = CKR_HOST_MEMORY;
2309                                 goto fail_cleanup;
2310                         }
2311 #ifdef  __sparcv9
2312                         if (big_init(&q,
2313                             (int)CHARLEN2BIGNUMLEN(subprime.big_value_len))
2314                             != BIG_OK) {
2315 #else   /* !__sparcv9 */
2316                         if (big_init(&q,
2317                             CHARLEN2BIGNUMLEN(subprime.big_value_len))
2318                             != BIG_OK) {
2319 #endif  /* __sparcv9 */
2320                                 rv = CKR_HOST_MEMORY;
2321                                 goto fail_cleanup;
2322                         }
2323                         bytestring2bignum(&x, value.big_value,
2324                             value.big_value_len);
2325                         bytestring2bignum(&q, subprime.big_value,
2326                             subprime.big_value_len);
2327 
2328                         if (big_cmp_abs(&x, &q) > 0) {
2329                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2330                                 goto fail_cleanup;
2331                         }
2332 
2333                         copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk));
2334 
2335                         copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk));
2336 
2337                         copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk));
2338 
2339                         copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk));
2340                 } else {
2341                         rv = CKR_TEMPLATE_INCOMPLETE;
2342                         goto fail_cleanup;
2343                 }
2344                 break;
2345 
2346         case CKK_DH:
2347                 if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2348                     isPrime2 || isExpo1 || isExpo2 || isCoef ||
2349                     isSubprime) {
2350                         rv = CKR_TEMPLATE_INCONSISTENT;
2351                         goto fail_cleanup;
2352                 }
2353 
2354                 /* CKA_VALUE_BITS is for key gen but not unwrap */
2355                 if (mode == SOFT_GEN_KEY)
2356                         KEY_PRI_DH_VAL_BITS(pvk) = (isValueBits) ?
2357                             value_bits : 0;
2358                 else if (mode == SOFT_UNWRAP_KEY) {
2359                         if (isValueBits) {
2360                                 rv = CKR_TEMPLATE_INCONSISTENT;
2361                                 goto fail_cleanup;
2362                         }
2363                 }
2364 
2365                 if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2366                         if (isPrime || isBase || isValue) {
2367                                 rv = CKR_TEMPLATE_INCONSISTENT;
2368                                 goto fail_cleanup;
2369                         } else
2370                                 break;
2371                 }
2372 
2373                 if (isValueBits) {
2374                         rv = CKR_TEMPLATE_INCONSISTENT;
2375                         goto fail_cleanup;
2376                 }
2377 
2378                 if (isPrime && isBase && isValue) {
2379                         copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk));
2380 
2381                         copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk));
2382 
2383                         copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk));
2384                 } else {
2385                         rv = CKR_TEMPLATE_INCOMPLETE;
2386                         goto fail_cleanup;
2387                 }
2388                 break;
2389 
2390         case CKK_X9_42_DH:
2391                 if (isModulus || isPubExpo || isPriExpo || isPrime1 ||
2392                     isPrime2 || isExpo1 || isExpo2 || isCoef ||
2393                     isValueBits) {
2394                         rv = CKR_TEMPLATE_INCONSISTENT;
2395                         goto fail_cleanup;
2396                 }
2397 
2398                 if (mode == SOFT_GEN_KEY || mode == SOFT_UNWRAP_KEY) {
2399                         if (isPrime || isSubprime || isBase || isValue) {
2400                                 rv = CKR_TEMPLATE_INCONSISTENT;
2401                                 goto fail_cleanup;
2402                         } else
2403                                 break;
2404                 }
2405 
2406                 if (isPrime && isSubprime && isBase && isValue) {
2407                         copy_bigint_attr(&prime, KEY_PRI_DH942_PRIME(pvk));
2408 
2409                         copy_bigint_attr(&base, KEY_PRI_DH942_BASE(pvk));
2410 
2411                         copy_bigint_attr(&subprime,
2412                             KEY_PRI_DH942_SUBPRIME(pvk));
2413 
2414                         copy_bigint_attr(&value, KEY_PRI_DH942_VALUE(pvk));
2415                 } else {
2416                         rv = CKR_TEMPLATE_INCOMPLETE;
2417                         goto fail_cleanup;
2418                 }
2419                 break;
2420 
2421         case CKK_EC:
2422                 if (isModulus || isPubExpo || isPrime ||
2423                     isPrime1 || isPrime2 || isExpo1 || isExpo2 || isCoef ||
2424                     isValueBits || isBase) {
2425                         rv = CKR_TEMPLATE_INCONSISTENT;
2426                         goto fail_cleanup;
2427 
2428                 } else if (isECParam) {
2429                         rv = soft_add_extra_attr(&param_tmp, new_object);
2430                         if (rv != CKR_OK)
2431                                 goto fail_cleanup;
2432                         string_attr_cleanup(&param_tmp);
2433                 }
2434                 if (isValue) {
2435                         copy_bigint_attr(&value, KEY_PRI_EC_VALUE(pvk));
2436                 }
2437                 break;
2438 
2439         default:
2440                 rv = CKR_TEMPLATE_INCONSISTENT;
2441                 goto fail_cleanup;
2442         }
2443 
2444         /* Set up object. */
2445         new_object->object_type = object_type;
2446         new_object->bool_attr_mask = attr_mask;
2447         if (isLabel) {
2448                 rv = soft_add_extra_attr(&string_tmp, new_object);
2449                 if (rv != CKR_OK)
2450                         goto fail_cleanup;
2451                 string_attr_cleanup(&string_tmp);
2452         }
2453         big_finish(&x);
2454         big_finish(&q);
2455 
2456         return (rv);
2457 
2458 fail_cleanup:
2459         /*
2460          * cleanup the storage allocated to the local variables.
2461          */
2462         bigint_attr_cleanup(&modulus);
2463         bigint_attr_cleanup(&priexpo);
2464         bigint_attr_cleanup(&prime);
2465         bigint_attr_cleanup(&subprime);
2466         bigint_attr_cleanup(&base);
2467         bigint_attr_cleanup(&value);
2468         bigint_attr_cleanup(&pubexpo);
2469         bigint_attr_cleanup(&prime1);
2470         bigint_attr_cleanup(&prime2);
2471         bigint_attr_cleanup(&expo1);
2472         bigint_attr_cleanup(&expo2);
2473         bigint_attr_cleanup(&coef);
2474         string_attr_cleanup(&string_tmp);
2475         string_attr_cleanup(&param_tmp);
2476         big_finish(&x);
2477         big_finish(&q);
2478 
2479         /*
2480          * cleanup the storage allocated inside the object itself.
2481          */
2482         soft_cleanup_object(new_object);
2483 
2484         return (rv);
2485 }
2486 
2487 
2488 /*
2489  * Build a Secret Key Object.
2490  *
2491  * - Parse the object's template, and when an error is detected such as
2492  *   invalid attribute type, invalid attribute value, etc., return
2493  *   with appropriate return value.
2494  * - Set up attribute mask field in the object for the supplied common
2495  *   attributes that have boolean type.
2496  * - Build the attribute_info struct to hold the value of each supplied
2497  *   attribute that has byte array type. Link attribute_info structs
2498  *   together to form the extra attribute list of the object.
2499  * - Allocate storage for the Secret Key object.
2500  * - Build the Secret Key object. Allocate storage to hold the big integer
2501  *   value for the attribute CKA_VALUE that is required for all the key
2502  *   types supported by secret key object.
2503  * This function is called internally with mode = SOFT_CREATE_OBJ_INT.
2504  *
2505  */
2506 CK_RV
2507 soft_build_secret_key_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
2508         soft_object_t *new_object, CK_ULONG mode, CK_ULONG key_len,
2509         CK_KEY_TYPE key_type)
2510 {
2511 
2512         ulong_t         i;
2513         CK_KEY_TYPE     keytype = (CK_KEY_TYPE)~0UL;
2514         uint64_t        attr_mask = SECRET_KEY_DEFAULT;
2515         CK_RV           rv = CKR_OK;
2516         int             isLabel = 0;
2517         /* Must set flags if mode != SOFT_UNWRAP_KEY, else must not set */
2518         int             isValue = 0;
2519         /* Must not set flags if mode != SOFT_UNWRAP_KEY, else optional */
2520         int             isValueLen = 0;
2521 
2522         CK_ATTRIBUTE    string_tmp;
2523 
2524         secret_key_obj_t  *sck;
2525         uchar_t object_type = 0;
2526 
2527         string_tmp.pValue = NULL;
2528 
2529         /* Allocate storage for Secret Key Object. */
2530         sck = calloc(1, sizeof (secret_key_obj_t));
2531         if (sck == NULL) {
2532                 rv = CKR_HOST_MEMORY;
2533                 goto fail_cleanup;
2534         }
2535 
2536         new_object->object_class_u.secret_key = sck;
2537         new_object->class = CKO_SECRET_KEY;
2538 
2539         for (i = 0; i < ulAttrNum; i++) {
2540 
2541                 /* Secret Key Object Attributes */
2542                 switch (template[i].type) {
2543 
2544                 /* common key attributes */
2545                 case CKA_KEY_TYPE:
2546                         keytype = *((CK_KEY_TYPE*)template[i].pValue);
2547                         break;
2548 
2549                 case CKA_ID:
2550                 case CKA_START_DATE:
2551                 case CKA_END_DATE:
2552                         /*
2553                          * Allocate storage to hold the attribute
2554                          * value with byte array type, and add it to
2555                          * the extra attribute list of the object.
2556                          */
2557                         rv = soft_add_extra_attr(&template[i],
2558                             new_object);
2559                         if (rv != CKR_OK) {
2560                                 goto fail_cleanup;
2561                         }
2562                         break;
2563 
2564                 /*
2565                  * The following key related attribute types must
2566                  * not be specified by C_CreateObject and C_GenerateKey.
2567                  */
2568                 case CKA_LOCAL:
2569                 case CKA_KEY_GEN_MECHANISM:
2570                 case CKA_ALWAYS_SENSITIVE:
2571                 case CKA_NEVER_EXTRACTABLE:
2572                         rv = CKR_TEMPLATE_INCONSISTENT;
2573                         goto fail_cleanup;
2574 
2575                 /* Key related boolean attributes */
2576                 case CKA_DERIVE:
2577                         if (*(CK_BBOOL *)template[i].pValue)
2578                                 attr_mask |= DERIVE_BOOL_ON;
2579                         break;
2580 
2581                 case CKA_SENSITIVE:
2582                         if (*(CK_BBOOL *)template[i].pValue)
2583                                 attr_mask |= SENSITIVE_BOOL_ON;
2584                         break;
2585 
2586                 case CKA_ENCRYPT:
2587                         if (*(CK_BBOOL *)template[i].pValue)
2588                                 attr_mask |= ENCRYPT_BOOL_ON;
2589                         else
2590                                 attr_mask &= ~ENCRYPT_BOOL_ON;
2591                         break;
2592 
2593                 case CKA_DECRYPT:
2594                         if (*(CK_BBOOL *)template[i].pValue)
2595                                 attr_mask |= DECRYPT_BOOL_ON;
2596                         else
2597                                 attr_mask &= ~DECRYPT_BOOL_ON;
2598                         break;
2599 
2600                 case CKA_SIGN:
2601                         if (*(CK_BBOOL *)template[i].pValue)
2602                                 attr_mask |= SIGN_BOOL_ON;
2603                         else
2604                                 attr_mask &= ~SIGN_BOOL_ON;
2605                         break;
2606 
2607                 case CKA_VERIFY:
2608                         if (*(CK_BBOOL *)template[i].pValue)
2609                                 attr_mask |= VERIFY_BOOL_ON;
2610                         else
2611                                 attr_mask &= ~VERIFY_BOOL_ON;
2612                         break;
2613 
2614                 case CKA_WRAP:
2615                         if (*(CK_BBOOL *)template[i].pValue)
2616                                 attr_mask |= WRAP_BOOL_ON;
2617                         else
2618                                 attr_mask &= ~WRAP_BOOL_ON;
2619                         break;
2620 
2621                 case CKA_UNWRAP:
2622                         if (*(CK_BBOOL *)template[i].pValue)
2623                                 attr_mask |= UNWRAP_BOOL_ON;
2624                         else
2625                                 attr_mask &= ~UNWRAP_BOOL_ON;
2626                         break;
2627 
2628                 case CKA_EXTRACTABLE:
2629                         if (*(CK_BBOOL *)template[i].pValue)
2630                                 attr_mask |= EXTRACTABLE_BOOL_ON;
2631                         else
2632                                 attr_mask &= ~EXTRACTABLE_BOOL_ON;
2633                         break;
2634 
2635                 case CKA_MODIFIABLE:
2636                         if ((*(CK_BBOOL *)template[i].pValue) == B_FALSE)
2637                                 attr_mask |= NOT_MODIFIABLE_BOOL_ON;
2638                         break;
2639 
2640                 case CKA_VALUE:
2641                         isValue = 1;
2642                         if (mode == SOFT_CREATE_OBJ) {
2643                                 if ((template[i].ulValueLen == 0) ||
2644                                     (template[i].pValue == NULL)) {
2645                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
2646                                         goto fail_cleanup;
2647                                 }
2648                         }
2649 
2650                         /*
2651                          * Copyin attribute from template
2652                          * to a local variable.
2653                          */
2654                         rv = get_bigint_attr_from_template((biginteger_t *)sck,
2655                             &template[i]);
2656                         if (rv != CKR_OK)
2657                                 goto fail_cleanup;
2658                         break;
2659 
2660                 case CKA_VALUE_LEN:
2661                         isValueLen = 1;
2662                         rv = get_ulong_attr_from_template(&sck->sk_value_len,
2663                             &template[i]);
2664                         if (rv != CKR_OK)
2665                                 goto fail_cleanup;
2666                         break;
2667 
2668                 case CKA_LABEL:
2669                         isLabel = 1;
2670                         rv = get_string_from_template(&string_tmp,
2671                             &template[i]);
2672                         if (rv != CKR_OK)
2673                                 goto fail_cleanup;
2674                         break;
2675 
2676                 default:
2677                         rv = soft_parse_common_attrs(&template[i],
2678                             &object_type);
2679                         if (rv != CKR_OK)
2680                                 goto fail_cleanup;
2681                         break;
2682 
2683                 }
2684         } /* For */
2685 
2686         switch (mode) {
2687         case SOFT_CREATE_OBJ:
2688         case SOFT_CREATE_OBJ_INT:
2689         case SOFT_DERIVE_KEY_DH:
2690                 /*
2691                  * The key type must be specified in the application's
2692                  * template. Otherwise, returns error.
2693                  */
2694                 if (keytype == (CK_KEY_TYPE)~0UL) {
2695                         rv = CKR_TEMPLATE_INCOMPLETE;
2696                         goto fail_cleanup;
2697                 }
2698                 break;
2699 
2700         case SOFT_GEN_KEY:
2701                 if (keytype == (CK_KEY_TYPE)~0UL) {
2702                         /*
2703                          * The key type is not specified in the application's
2704                          * template, so we use the implied key type based on
2705                          * the mechanism.
2706                          */
2707                         keytype = key_type;
2708                 } else {
2709                         if (keytype != key_type) {
2710                                 /*
2711                                  * The key type specified in the template
2712                                  * does not match the implied key type based
2713                                  * on the mechanism.
2714                                  */
2715                                 rv = CKR_TEMPLATE_INCONSISTENT;
2716                                 goto fail_cleanup;
2717                         }
2718                 }
2719 
2720                 /*
2721                  * If a key_len is passed as a parameter, it has to
2722                  * match the one found in the template.
2723                  */
2724                 if (key_len > 0) {
2725                         if (isValueLen && sck->sk_value_len != key_len) {
2726                                 rv = CKR_TEMPLATE_INCONSISTENT;
2727                                 goto fail_cleanup;
2728                         }
2729                         isValueLen = 1;
2730                         sck->sk_value_len = key_len;
2731                 }
2732                 break;
2733 
2734         case SOFT_UNWRAP_KEY:
2735                 /*
2736                  * Note that, for mode SOFT_UNWRAP_KEY, key type is not
2737                  * implied by the mechanism (key_type), so if it is not
2738                  * specified from the attribute template (keytype), it is
2739                  * incomplete.
2740                  */
2741                 if (keytype == (CK_KEY_TYPE)~0UL) {
2742                         rv = CKR_TEMPLATE_INCOMPLETE;
2743                         goto fail_cleanup;
2744                 }
2745                 break;
2746 
2747         case SOFT_DERIVE_KEY_OTHER:
2748                 /*
2749                  * For CKM_MD5_KEY_DERIVATION & CKM_SHA1_KEY_DERIVATION, the
2750                  * key type is optional.
2751                  */
2752                 if (keytype == (CK_KEY_TYPE)~0UL) {
2753                         keytype = key_type;
2754                 }
2755                 break;
2756         }
2757 
2758         switch (mode) {
2759         case SOFT_CREATE_OBJ:
2760         case SOFT_CREATE_OBJ_INT:
2761                 switch (keytype) {
2762                 case CKK_RC4:
2763                         if (!isValue) {
2764                                 rv = CKR_TEMPLATE_INCOMPLETE;
2765                                 goto fail_cleanup;
2766                         }
2767                         if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2768                             (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2769                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2770                                 goto fail_cleanup;
2771                         }
2772                         break;
2773 
2774                 case CKK_GENERIC_SECRET:
2775                         if (!isValue) {
2776                                 rv = CKR_TEMPLATE_INCOMPLETE;
2777                                 goto fail_cleanup;
2778                         }
2779                         break;
2780 
2781                 case CKK_AES:
2782                         if (!isValue) {
2783                                 rv = CKR_TEMPLATE_INCOMPLETE;
2784                                 goto fail_cleanup;
2785                         }
2786                         if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2787                             (sck->sk_value_len != AES_192_KEY_BYTES) &&
2788                             (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2789                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2790                                 goto fail_cleanup;
2791                         }
2792                         break;
2793 
2794                 case CKK_BLOWFISH:
2795                         if (!isValue) {
2796                                 rv = CKR_TEMPLATE_INCOMPLETE;
2797                                 goto fail_cleanup;
2798                         }
2799                         if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2800                             (sck->sk_value_len > BLOWFISH_MAXBYTES)) {
2801                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2802                                 goto fail_cleanup;
2803                         }
2804 
2805                         break;
2806 
2807                 case CKK_DES:
2808                         if (!isValue) {
2809                                 rv = CKR_TEMPLATE_INCOMPLETE;
2810                                 goto fail_cleanup;
2811                         }
2812                         if (sck->sk_value_len != DES_KEYSIZE) {
2813                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2814                                 goto fail_cleanup;
2815                         }
2816                         break;
2817 
2818                 case CKK_DES2:
2819                         if (!isValue) {
2820                                 rv = CKR_TEMPLATE_INCOMPLETE;
2821                                 goto fail_cleanup;
2822                         }
2823                         if (sck->sk_value_len != DES2_KEYSIZE) {
2824                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2825                                 goto fail_cleanup;
2826                         }
2827                         break;
2828 
2829                 case CKK_DES3:
2830                         if (!isValue) {
2831                                 rv = CKR_TEMPLATE_INCOMPLETE;
2832                                 goto fail_cleanup;
2833                         }
2834                         if (sck->sk_value_len != DES3_KEYSIZE) {
2835                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2836                                 goto fail_cleanup;
2837                         }
2838                         break;
2839 
2840                 default:
2841                         rv = CKR_TEMPLATE_INCONSISTENT;
2842                         goto fail_cleanup;
2843                 }
2844 
2845                 if (isValueLen) {
2846                         /*
2847                          * Templates for internal object creation come from
2848                          * applications calls to C_DeriveKey(), for which it
2849                          * is OKey to pass a CKA_VALUE_LEN attribute, as
2850                          * long as it does not conflict with the length of the
2851                          * CKA_VALUE attribute.
2852                          */
2853                         if ((mode != SOFT_CREATE_OBJ_INT) ||
2854                             ((key_len > 0) && sck->sk_value_len != key_len)) {
2855                                 rv = CKR_TEMPLATE_INCONSISTENT;
2856                                 goto fail_cleanup;
2857                         }
2858                 }
2859                 break;
2860 
2861         case SOFT_GEN_KEY:
2862                 /* CKA_VALUE must not be specified */
2863                 if (isValue) {
2864                         rv = CKR_TEMPLATE_INCONSISTENT;
2865                         goto fail_cleanup;
2866                 }
2867 
2868                 switch (keytype) {
2869                 /*
2870                  * CKA_VALUE_LEN must be specified by C_GenerateKey
2871                  * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
2872                  */
2873                 case CKK_RC4:
2874                         if (!isValueLen) {
2875                                 rv = CKR_TEMPLATE_INCOMPLETE;
2876                                 goto fail_cleanup;
2877                         }
2878                         ;
2879                         if ((sck->sk_value_len < ARCFOUR_MIN_KEY_BYTES) ||
2880                             (sck->sk_value_len > ARCFOUR_MAX_KEY_BYTES)) {
2881                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2882                                 goto fail_cleanup;
2883                         }
2884                         break;
2885 
2886                 case CKK_GENERIC_SECRET:
2887                         /* arbitrary key length - no length checking */
2888                         if (!isValueLen) {
2889                                 rv = CKR_TEMPLATE_INCOMPLETE;
2890                                 goto fail_cleanup;
2891                         }
2892                         break;
2893 
2894                 case CKK_AES:
2895                         if (!isValueLen) {
2896                                 rv = CKR_TEMPLATE_INCOMPLETE;
2897                                 goto fail_cleanup;
2898                         }
2899 
2900                         if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2901                             (sck->sk_value_len != AES_192_KEY_BYTES) &&
2902                             (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2903                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2904                                 goto fail_cleanup;
2905                         }
2906 
2907                         break;
2908 
2909                 case CKK_BLOWFISH:
2910                         if (!isValueLen) {
2911                                 rv = CKR_TEMPLATE_INCOMPLETE;
2912                                 goto fail_cleanup;
2913                         }
2914                         if ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2915                             (sck->sk_value_len > BLOWFISH_MAXBYTES)) {
2916                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2917                                 goto fail_cleanup;
2918                         }
2919 
2920                         break;
2921 
2922                 case CKK_DES:
2923                 case CKK_DES2:
2924                 case CKK_DES3:
2925                         /* CKA_VALUE_LEN attribute does not apply to DES<n> */
2926                         if (isValueLen) {
2927                                 rv = CKR_TEMPLATE_INCONSISTENT;
2928                                 goto fail_cleanup;
2929                         }
2930                         break;
2931 
2932                 default:
2933                         rv = CKR_TEMPLATE_INCONSISTENT;
2934                         goto fail_cleanup;
2935                 }
2936                 break;
2937 
2938         case SOFT_UNWRAP_KEY:
2939                 /*
2940                  * According to v2.11 of PKCS#11 spec, neither CKA_VALUE nor
2941                  * CKA_VALUE_LEN can be be specified; however v2.20 has this
2942                  * restriction removed, perhaps because it makes it hard to
2943                  * determine variable-length key sizes.  This case statement
2944                  * complied with v2.20.
2945                  */
2946                 if (isValue) {
2947                         rv = CKR_TEMPLATE_INCONSISTENT;
2948                         goto fail_cleanup;
2949                 }
2950 
2951                 switch (keytype) {
2952                 /*
2953                  * CKA_VALUE_LEN is optional
2954                  * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2955                  * and the unwrapping mech is *_CBC_PAD.
2956                  *
2957                  * CKA_VALUE_LEN is required
2958                  * if key is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET
2959                  * and the unwrapping mech is *_ECB or *_CBC.
2960                  *
2961                  * since mech is not known at this point, CKA_VALUE_LEN is
2962                  * treated as optional and the caller needs to enforce it.
2963                  */
2964                 case CKK_RC4:
2965                         if (isValueLen) {
2966                                 if ((sck->sk_value_len <
2967                                     ARCFOUR_MIN_KEY_BYTES) ||
2968                                     (sck->sk_value_len >
2969                                     ARCFOUR_MAX_KEY_BYTES)) {
2970                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
2971                                         goto fail_cleanup;
2972                                 }
2973                         }
2974                         break;
2975 
2976                 case CKK_GENERIC_SECRET:
2977                         /* arbitrary key length - no length checking */
2978                         break;
2979 
2980                 case CKK_AES:
2981                         if (isValueLen) {
2982                                 if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
2983                                     (sck->sk_value_len != AES_192_KEY_BYTES) &&
2984                                     (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
2985                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
2986                                         goto fail_cleanup;
2987                                 }
2988                         }
2989                         break;
2990 
2991                 case CKK_BLOWFISH:
2992                         if (isValueLen &&
2993                             ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
2994                             (sck->sk_value_len > BLOWFISH_MAXBYTES))) {
2995                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
2996                                 goto fail_cleanup;
2997                         }
2998                         break;
2999 
3000                 case CKK_DES:
3001                 case CKK_DES2:
3002                 case CKK_DES3:
3003                         /* CKA_VALUE_LEN attribute does not apply to DES<n> */
3004                         if (isValueLen) {
3005                                 rv = CKR_TEMPLATE_INCONSISTENT;
3006                                 goto fail_cleanup;
3007                         }
3008                         break;
3009 
3010                 default:
3011                         rv = CKR_TEMPLATE_INCONSISTENT;
3012                         goto fail_cleanup;
3013                 }
3014                 break;
3015 
3016         case SOFT_DERIVE_KEY_DH:
3017                 /* CKA_VALUE must not be specified */
3018                 if (isValue) {
3019                         rv = CKR_TEMPLATE_INCONSISTENT;
3020                         goto fail_cleanup;
3021                 }
3022 
3023                 switch (keytype) {
3024                 /*
3025                  * CKA_VALUE_LEN is optional
3026                  * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
3027                  */
3028                 case CKK_RC4:
3029                         if (isValueLen) {
3030                                 if ((sck->sk_value_len <
3031                                     ARCFOUR_MIN_KEY_BYTES) ||
3032                                     (sck->sk_value_len >
3033                                     ARCFOUR_MAX_KEY_BYTES)) {
3034                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
3035                                         goto fail_cleanup;
3036                                 }
3037                         }
3038                         break;
3039 
3040                 case CKK_GENERIC_SECRET:
3041                         /* arbitrary key length - no length checking */
3042                         break;
3043 
3044                 case CKK_AES:
3045                         if (isValueLen) {
3046                                 if ((sck->sk_value_len != AES_MIN_KEY_BYTES) &&
3047                                     (sck->sk_value_len != AES_192_KEY_BYTES) &&
3048                                     (sck->sk_value_len != AES_MAX_KEY_BYTES)) {
3049                                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
3050                                         goto fail_cleanup;
3051                                 }
3052                         }
3053 
3054                         break;
3055 
3056                 case CKK_BLOWFISH:
3057                         if (isValueLen &&
3058                             ((sck->sk_value_len < BLOWFISH_MINBYTES) ||
3059                             (sck->sk_value_len > BLOWFISH_MAXBYTES))) {
3060                                 rv = CKR_ATTRIBUTE_VALUE_INVALID;
3061                                 goto fail_cleanup;
3062                         }
3063                         break;
3064 
3065                 case CKK_DES:
3066                 case CKK_DES2:
3067                 case CKK_DES3:
3068                         /* CKA_VALUE_LEN attribute does not apply to DES<n> */
3069                         if (isValueLen) {
3070                                 rv = CKR_TEMPLATE_INCONSISTENT;
3071                                 goto fail_cleanup;
3072                         }
3073                         break;
3074 
3075                 default:
3076                         rv = CKR_TEMPLATE_INCONSISTENT;
3077                         goto fail_cleanup;
3078                 }
3079                 break;
3080 
3081         case SOFT_DERIVE_KEY_OTHER:
3082                 /* CKA_VALUE must not be specified */
3083                 if (isValue) {
3084                         rv = CKR_TEMPLATE_INCONSISTENT;
3085                         goto fail_cleanup;
3086                 }
3087 
3088                 switch (keytype) {
3089                 /*
3090                  * CKA_VALUE_LEN is an optional attribute for
3091                  * CKM_SHA1_KEY_DERIVATION and CKM_MD5_KEY_DERIVATION
3092                  * if mech is CKK_RC4, CKK_AES, CKK_GENERIC_SECRET.
3093                  */
3094                 case CKK_RC4:
3095                 case CKK_GENERIC_SECRET:
3096                 case CKK_AES:
3097                 case CKK_BLOWFISH:
3098                         /*
3099                          * No need to check key length value here, it will be
3100                          * validated later in soft_key_derive_check_length().
3101                          */
3102                         break;
3103 
3104                 case CKK_DES:
3105                 case CKK_DES2:
3106                 case CKK_DES3:
3107                         /* CKA_VALUE_LEN attribute does not apply to DES<n> */
3108                         if (isValueLen) {
3109                                 rv = CKR_TEMPLATE_INCONSISTENT;
3110                                 goto fail_cleanup;
3111                         }
3112                         break;
3113 
3114                 default:
3115                         rv = CKR_TEMPLATE_INCONSISTENT;
3116                         goto fail_cleanup;
3117                 }
3118                 break;
3119         }
3120 
3121         /* Set up object. */
3122         new_object->key_type = keytype;
3123         new_object->object_type = object_type;
3124         new_object->bool_attr_mask = attr_mask;
3125         if (isLabel) {
3126                 rv = soft_add_extra_attr(&string_tmp, new_object);
3127                 if (rv != CKR_OK)
3128                         goto fail_cleanup;
3129                 string_attr_cleanup(&string_tmp);
3130         }
3131         return (rv);
3132 
3133 fail_cleanup:
3134         /*
3135          * cleanup the storage allocated to the local variables.
3136          */
3137         bigint_attr_cleanup((biginteger_t *)sck);
3138         string_attr_cleanup(&string_tmp);
3139 
3140         /*
3141          * cleanup the storage allocated inside the object itself.
3142          */
3143         soft_cleanup_object(new_object);
3144 
3145         return (rv);
3146 }
3147 
3148 
3149 /*
3150  * Build a Domain Parameter Object.
3151  *
3152  * - Parse the object's template, and when an error is detected such as
3153  *   invalid attribute type, invalid attribute value, etc., return
3154  *   with appropriate return value.
3155  * - Allocate storage for the Domain Parameter object.
3156  * - Build the Domain Parameter object according to the key type. Allocate
3157  *   storage to hold the big integer value for the supplied attributes
3158  *   that are required for a certain key type.
3159  *
3160  */
3161 CK_RV
3162 soft_build_domain_parameters_object(CK_ATTRIBUTE_PTR template,
3163         CK_ULONG ulAttrNum, soft_object_t *new_object)
3164 {
3165 
3166         ulong_t         i;
3167         CK_KEY_TYPE     keytype = (CK_KEY_TYPE)~0UL;
3168         CK_RV           rv = CKR_OK;
3169         int             isLabel = 0;
3170         /* Must set flags */
3171         int             isPrime = 0;
3172         int             isSubprime = 0;
3173         int             isBase = 0;
3174         /* Must not set flags */
3175         int             isPrimeBits = 0;
3176         int             isSubPrimeBits = 0;
3177 
3178         biginteger_t    prime;
3179         biginteger_t    subprime;
3180         biginteger_t    base;
3181         CK_ATTRIBUTE    string_tmp;
3182 
3183         domain_obj_t    *dom;
3184         uchar_t object_type = 0;
3185 
3186         /* prevent bigint_attr_cleanup from freeing invalid attr value */
3187         (void) memset(&prime, 0x0, sizeof (biginteger_t));
3188         (void) memset(&subprime, 0x0, sizeof (biginteger_t));
3189         (void) memset(&base, 0x0, sizeof (biginteger_t));
3190         string_tmp.pValue = NULL;
3191 
3192         for (i = 0; i < ulAttrNum; i++) {
3193 
3194                 /* Domain Parameters Object Attributes */
3195                 switch (template[i].type) {
3196 
3197                 /* common domain parameter attribute */
3198                 case CKA_KEY_TYPE:
3199                         keytype = *((CK_KEY_TYPE*)template[i].pValue);
3200                         break;
3201 
3202                 /*
3203                  * The following common domain parameter attribute
3204                  * must not be specified by C_CreateObject.
3205                  */
3206                 case CKA_LOCAL:
3207                         rv = CKR_TEMPLATE_INCONSISTENT;
3208                         goto fail_cleanup;
3209 
3210                 /*
3211                  * The following domain parameter attributes must be
3212                  * specified according to the key type by
3213                  * C_CreateObject.
3214                  */
3215                 case CKA_PRIME:
3216                         isPrime = 1;
3217                         /*
3218                          * Copyin big integer attribute from template
3219                          * to a local variable.
3220                          */
3221                         rv = get_bigint_attr_from_template(&prime,
3222                             &template[i]);
3223                         if (rv != CKR_OK)
3224                                 goto fail_cleanup;
3225                         break;
3226 
3227                 case CKA_SUBPRIME:
3228                         isSubprime = 1;
3229                         rv = get_bigint_attr_from_template(&subprime,
3230                             &template[i]);
3231                         if (rv != CKR_OK)
3232                                 goto fail_cleanup;
3233                         break;
3234 
3235                 case CKA_BASE:
3236                         isBase = 1;
3237                         rv = get_bigint_attr_from_template(&base,
3238                             &template[i]);
3239                         if (rv != CKR_OK)
3240                                 goto fail_cleanup;
3241                         break;
3242 
3243                 case CKA_PRIME_BITS:
3244                         isPrimeBits = 1;
3245                         break;
3246 
3247                 case CKA_SUB_PRIME_BITS:
3248                         isSubPrimeBits = 1;
3249                         break;
3250 
3251                 case CKA_LABEL:
3252                         isLabel = 1;
3253                         rv = get_string_from_template(&string_tmp,
3254                             &template[i]);
3255                         if (rv != CKR_OK)
3256                                 goto fail_cleanup;
3257                         break;
3258 
3259                 default:
3260                         rv = soft_parse_common_attrs(&template[i],
3261                             &object_type);
3262                         if (rv != CKR_OK)
3263                                 goto fail_cleanup;
3264                         break;
3265 
3266                 }
3267         } /* For */
3268 
3269         /* Allocate storage for Domain Parameters Object. */
3270         dom = calloc(1, sizeof (domain_obj_t));
3271         if (dom == NULL) {
3272                 rv = CKR_HOST_MEMORY;
3273                 goto fail_cleanup;
3274         }
3275 
3276         new_object->object_class_u.domain = dom;
3277         new_object->class = CKO_DOMAIN_PARAMETERS;
3278 
3279         if (keytype == (CK_KEY_TYPE)~0UL) {
3280                 rv = CKR_TEMPLATE_INCOMPLETE;
3281                 goto fail_cleanup;
3282         }
3283 
3284         new_object->key_type = keytype;
3285 
3286         /* Supported key types of the Domain Parameters Object */
3287         switch (keytype) {
3288         case CKK_DSA:
3289                 if (isPrimeBits || isSubPrimeBits) {
3290                         rv = CKR_TEMPLATE_INCONSISTENT;
3291                         goto fail_cleanup;
3292                 }
3293 
3294                 if (isPrime && isSubprime && isBase) {
3295                         /*
3296                          * Copy big integer attribute value to the
3297                          * designated place in the domain parameter
3298                          * object.
3299                          */
3300                         copy_bigint_attr(&prime, KEY_DOM_DSA_PRIME(dom));
3301 
3302                         copy_bigint_attr(&subprime, KEY_DOM_DSA_SUBPRIME(dom));
3303 
3304                         copy_bigint_attr(&base, KEY_DOM_DSA_BASE(dom));
3305                 } else {
3306                         rv = CKR_TEMPLATE_INCOMPLETE;
3307                         goto fail_cleanup;
3308                 }
3309                 break;
3310 
3311         case CKK_DH:
3312                 if (isPrimeBits || isSubprime || isSubPrimeBits) {
3313                         rv = CKR_TEMPLATE_INCONSISTENT;
3314                         goto fail_cleanup;
3315                 }
3316 
3317                 if (isPrime && isBase) {
3318                         copy_bigint_attr(&prime, KEY_DOM_DH_PRIME(dom));
3319 
3320                         copy_bigint_attr(&base, KEY_DOM_DH_BASE(dom));
3321                 } else {
3322                         rv = CKR_TEMPLATE_INCOMPLETE;
3323                         goto fail_cleanup;
3324                 }
3325                 break;
3326 
3327         case CKK_X9_42_DH:
3328                 if (isPrimeBits || isSubPrimeBits) {
3329                         rv = CKR_TEMPLATE_INCONSISTENT;
3330                         goto fail_cleanup;
3331                 }
3332 
3333                 if (isPrime && isSubprime && isBase) {
3334                         copy_bigint_attr(&prime, KEY_DOM_DH942_PRIME(dom));
3335 
3336                         copy_bigint_attr(&base, KEY_DOM_DH942_BASE(dom));
3337 
3338                         copy_bigint_attr(&subprime,
3339                             KEY_DOM_DH942_SUBPRIME(dom));
3340                 } else {
3341                         rv = CKR_TEMPLATE_INCOMPLETE;
3342                         goto fail_cleanup;
3343                 }
3344                 break;
3345 
3346         default:
3347                 rv = CKR_TEMPLATE_INCONSISTENT;
3348                 goto fail_cleanup;
3349         }
3350 
3351         new_object->object_type = object_type;
3352 
3353         if (isLabel) {
3354                 rv = soft_add_extra_attr(&string_tmp, new_object);
3355                 if (rv != CKR_OK)
3356                         goto fail_cleanup;
3357                 string_attr_cleanup(&string_tmp);
3358         }
3359 
3360         return (rv);
3361 
3362 fail_cleanup:
3363         /*
3364          * cleanup the storage allocated to the local variables.
3365          */
3366         bigint_attr_cleanup(&prime);
3367         bigint_attr_cleanup(&subprime);
3368         bigint_attr_cleanup(&base);
3369         string_attr_cleanup(&string_tmp);
3370 
3371         /*
3372          * cleanup the storage allocated inside the object itself.
3373          */
3374         soft_cleanup_object(new_object);
3375 
3376         return (rv);
3377 }
3378 
3379 /*
3380  * Build a Certificate Object
3381  *
3382  * - Parse the object's template, and when an error is detected such as
3383  *   invalid attribute type, invalid attribute value, etc., return
3384  *   with appropriate return value.
3385  * - Allocate storage for the Certificate object
3386  */
3387 static CK_RV
3388 soft_build_certificate_object(CK_ATTRIBUTE_PTR template,
3389         CK_ULONG ulAttrNum, soft_object_t *new_object,
3390         CK_CERTIFICATE_TYPE cert_type)
3391 {
3392         uint64_t        attr_mask = 0;
3393         CK_RV           rv = CKR_OK;
3394         CK_ULONG        i;
3395         int             owner_set = 0;
3396         int             value_set = 0;
3397         int             subject_set = 0;
3398         certificate_obj_t *cert;
3399         /* certificate type defaults to the value given as a parameter */
3400         CK_CERTIFICATE_TYPE certtype = cert_type;
3401         CK_ATTRIBUTE    string_tmp;
3402         int             isLabel = 0;
3403         uchar_t         object_type = 0;
3404 
3405         /*
3406          * Look for the certificate type attribute and do some
3407          * sanity checking before creating the structures.
3408          */
3409         for (i = 0; i < ulAttrNum; i++) {
3410                 /* Certificate Object Attributes */
3411                 switch (template[i].type) {
3412                         case CKA_CERTIFICATE_TYPE:
3413                                 certtype =
3414                                     *((CK_CERTIFICATE_TYPE*)template[i].pValue);
3415                                 break;
3416                         case CKA_SUBJECT:
3417                                 subject_set = 1;
3418                                 break;
3419                         case CKA_OWNER:
3420                                 owner_set = 1;
3421                                 break;
3422                         case CKA_VALUE:
3423                                 value_set = 1;
3424                                 break;
3425                 }
3426         }
3427 
3428         /* The certificate type MUST be specified */
3429         if (certtype != CKC_X_509 && certtype != CKC_X_509_ATTR_CERT)
3430                 return (CKR_TEMPLATE_INCOMPLETE);
3431 
3432         /*
3433          * For X.509 certs, the CKA_SUBJECT and CKA_VALUE
3434          * must be present at creation time.
3435          */
3436         if (certtype == CKC_X_509 &&
3437             (!subject_set || !value_set))
3438                 return (CKR_TEMPLATE_INCOMPLETE);
3439 
3440         /*
3441          * For X.509 Attribute certs, the CKA_OWNER and CKA_VALUE
3442          * must be present at creation time.
3443          */
3444         if (certtype == CKC_X_509_ATTR_CERT &&
3445             (!owner_set || !value_set))
3446                 return (CKR_TEMPLATE_INCOMPLETE);
3447 
3448         string_tmp.pValue = NULL;
3449         cert = calloc(1, sizeof (certificate_obj_t));
3450         if (cert == NULL) {
3451                 return (CKR_HOST_MEMORY);
3452         }
3453         cert->certificate_type = certtype;
3454 
3455         for (i = 0; i < ulAttrNum; i++) {
3456                 /* Certificate Object Attributes */
3457                 switch (certtype) {
3458                         case CKC_X_509:
3459                         switch (template[i].type) {
3460                                 case CKA_SUBJECT:
3461                                         rv = get_cert_attr_from_template(
3462                                             &cert->cert_type_u.x509.subject,
3463                                             &template[i]);
3464                                         break;
3465                                 case CKA_VALUE:
3466                                         rv = get_cert_attr_from_template(
3467                                             &cert->cert_type_u.x509.value,
3468                                             &template[i]);
3469                                         break;
3470                                 case CKA_LABEL:
3471                                         isLabel = 1;
3472                                         rv = get_string_from_template(
3473                                             &string_tmp,
3474                                             &template[i]);
3475                                         if (rv != CKR_OK)
3476                                                 goto fail_cleanup;
3477                                         break;
3478                                 case CKA_ID:
3479                                 case CKA_ISSUER:
3480                                 case CKA_SERIAL_NUMBER:
3481                                         rv = soft_add_extra_attr(&template[i],
3482                                             new_object);
3483                                         break;
3484                                 case CKA_MODIFIABLE:
3485                                         if ((*(CK_BBOOL *)template[i].pValue) ==
3486                                             B_FALSE)
3487                                                 attr_mask |=
3488                                                     NOT_MODIFIABLE_BOOL_ON;
3489                                         break;
3490                                 case CKA_CERTIFICATE_TYPE:
3491                                         break;
3492                                 default:
3493                                         rv = soft_parse_common_attrs(
3494                                             &template[i], &object_type);
3495                                         if (rv != CKR_OK)
3496                                                 goto fail_cleanup;
3497                         }
3498                         break;
3499                         case CKC_X_509_ATTR_CERT:
3500                         switch (template[i].type) {
3501                                 case CKA_OWNER:
3502                                         rv = get_cert_attr_from_template(
3503                                             &cert->cert_type_u.x509_attr.owner,
3504                                             &template[i]);
3505                                         break;
3506                                 case CKA_VALUE:
3507                                         rv = get_cert_attr_from_template(
3508                                             &cert->cert_type_u.x509_attr.value,
3509                                             &template[i]);
3510                                         break;
3511                                 case CKA_LABEL:
3512                                         isLabel = 1;
3513                                         rv = get_string_from_template(
3514                                             &string_tmp, &template[i]);
3515                                         if (rv != CKR_OK)
3516                                                 goto fail_cleanup;
3517                                         break;
3518                                 case CKA_SERIAL_NUMBER:
3519                                 case CKA_AC_ISSUER:
3520                                 case CKA_ATTR_TYPES:
3521                                         rv = soft_add_extra_attr(&template[i],
3522                                             new_object);
3523                                         break;
3524 
3525                                 case CKA_MODIFIABLE:
3526                                         if ((*(CK_BBOOL *)template[i].pValue) ==
3527                                             B_FALSE)
3528                                                 attr_mask |=
3529                                                     NOT_MODIFIABLE_BOOL_ON;
3530                                         break;
3531                                 case CKA_CERTIFICATE_TYPE:
3532                                         break;
3533                                 default:
3534                                         rv = soft_parse_common_attrs(
3535                                             &template[i], &object_type);
3536                                         if (rv != CKR_OK)
3537                                                 goto fail_cleanup;
3538                                         break;
3539                         }
3540                         break;
3541                         default:
3542                                 rv = CKR_TEMPLATE_INCOMPLETE;
3543                                 break;
3544                 }
3545         }
3546 
3547         if (rv == CKR_OK) {
3548                 new_object->object_class_u.certificate = cert;
3549                 new_object->class = CKO_CERTIFICATE;
3550                 new_object->object_type = object_type;
3551                 new_object->cert_type = certtype;
3552                 new_object->bool_attr_mask = attr_mask;
3553                 if (isLabel) {
3554                         rv = soft_add_extra_attr(&string_tmp, new_object);
3555                         if (rv != CKR_OK)
3556                                 goto fail_cleanup;
3557                         string_attr_cleanup(&string_tmp);
3558                 }
3559         }
3560 
3561 fail_cleanup:
3562         if (rv != CKR_OK) {
3563                 soft_cleanup_cert_object(new_object);
3564         }
3565         return (rv);
3566 }
3567 
3568 
3569 /*
3570  * Validate the attribute types in the object's template. Then,
3571  * call the appropriate build function according to the class of
3572  * the object specified in the template.
3573  *
3574  * Note: The following classes of objects are supported:
3575  * - CKO_PUBLIC_KEY
3576  * - CKO_PRIVATE_KEY
3577  * - CKO_SECRET_KEY
3578  * - CKO_DOMAIN_PARAMETERS
3579  * - CKO_CERTIFICATE
3580  *
3581  */
3582 CK_RV
3583 soft_build_object(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3584         soft_object_t *new_object)
3585 {
3586 
3587         CK_OBJECT_CLASS class = (CK_OBJECT_CLASS)~0UL;
3588         CK_RV           rv = CKR_OK;
3589 
3590         if (template == NULL) {
3591                 return (CKR_ARGUMENTS_BAD);
3592         }
3593 
3594         /* Validate the attribute type in the template. */
3595         rv = soft_validate_attr(template, ulAttrNum, &class);
3596         if (rv != CKR_OK)
3597                 return (rv);
3598         /*
3599          * CKA_CLASS is a mandatory attribute for C_CreateObject
3600          */
3601         if (class == (CK_OBJECT_CLASS)~0UL)
3602                 return (CKR_TEMPLATE_INCOMPLETE);
3603 
3604         /*
3605          * Call the appropriate function based on the supported class
3606          * of the object.
3607          */
3608         switch (class) {
3609         case CKO_PUBLIC_KEY:
3610                 rv = soft_build_public_key_object(template, ulAttrNum,
3611                     new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3612                 break;
3613 
3614         case CKO_PRIVATE_KEY:
3615                 rv = soft_build_private_key_object(template, ulAttrNum,
3616                     new_object, SOFT_CREATE_OBJ, (CK_KEY_TYPE)~0UL);
3617                 break;
3618 
3619         case CKO_SECRET_KEY:
3620                 rv = soft_build_secret_key_object(template, ulAttrNum,
3621                     new_object, SOFT_CREATE_OBJ, 0, (CK_KEY_TYPE)~0UL);
3622                 break;
3623 
3624         case CKO_DOMAIN_PARAMETERS:
3625                 rv = soft_build_domain_parameters_object(template, ulAttrNum,
3626                     new_object);
3627                 break;
3628 
3629         case CKO_CERTIFICATE:
3630                 rv = soft_build_certificate_object(template, ulAttrNum,
3631                     new_object, (CK_CERTIFICATE_TYPE)~0UL);
3632                 break;
3633 
3634         case CKO_DATA:
3635         case CKO_HW_FEATURE:
3636         case CKO_VENDOR_DEFINED:
3637         default:
3638                 return (CKR_ATTRIBUTE_VALUE_INVALID);
3639         }
3640 
3641         return (rv);
3642 }
3643 
3644 /*
3645  * Validate the attribute types in the object's template. Then,
3646  * call the appropriate build function according to the class of
3647  * the object specified in the template.
3648  *
3649  */
3650 CK_RV
3651 soft_build_key(CK_ATTRIBUTE_PTR template, CK_ULONG ulAttrNum,
3652         soft_object_t *new_object, CK_OBJECT_CLASS class, CK_KEY_TYPE key_type,
3653         CK_ULONG key_len, CK_ULONG mode)
3654 {
3655 
3656         CK_RV           rv = CKR_OK;
3657         CK_OBJECT_CLASS temp_class = (CK_OBJECT_CLASS)~0UL;
3658 
3659         /* Validate the attribute type in the template. */
3660         if ((template != NULL) && (ulAttrNum != 0)) {
3661                 rv = soft_validate_attr(template, ulAttrNum, &temp_class);
3662                 if (rv != CKR_OK)
3663                         return (rv);
3664         }
3665 
3666         /*
3667          * If either the class from the parameter list ("class") or
3668          * the class from the template ("temp_class") is not specified,
3669          * try to use the other one.
3670          */
3671         if (temp_class == (CK_OBJECT_CLASS)~0UL) {
3672                 temp_class = class;
3673         } else if (class == (CK_OBJECT_CLASS)~0UL) {
3674                 class = temp_class;
3675         }
3676 
3677         /* If object class is still not specified, template is incomplete. */
3678         if (class == (CK_OBJECT_CLASS)~0UL)
3679                 return (CKR_TEMPLATE_INCOMPLETE);
3680 
3681         /* Class should match if specified in both parameters and template. */
3682         if (class != temp_class)
3683                 return (CKR_TEMPLATE_INCONSISTENT);
3684 
3685         /*
3686          * Call the appropriate function based on the supported class
3687          * of the object.
3688          */
3689         switch (class) {
3690         case CKO_PUBLIC_KEY:
3691 
3692                 /* Unwrapping public keys is not supported. */
3693                 if (mode == SOFT_UNWRAP_KEY) {
3694                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
3695                         break;
3696                 }
3697 
3698                 rv = soft_build_public_key_object(template, ulAttrNum,
3699                     new_object, mode, key_type);
3700                 break;
3701 
3702         case CKO_PRIVATE_KEY:
3703 
3704                 rv = soft_build_private_key_object(template, ulAttrNum,
3705                     new_object, mode, key_type);
3706                 break;
3707 
3708         case CKO_SECRET_KEY:
3709 
3710                 rv = soft_build_secret_key_object(template, ulAttrNum,
3711                     new_object, mode, key_len, key_type);
3712                 break;
3713 
3714         case CKO_DOMAIN_PARAMETERS:
3715 
3716                 /* Unwrapping domain parameters is not supported. */
3717                 if (mode == SOFT_UNWRAP_KEY) {
3718                         rv = CKR_ATTRIBUTE_VALUE_INVALID;
3719                         break;
3720                 }
3721 
3722                 rv = soft_build_domain_parameters_object(template, ulAttrNum,
3723                     new_object);
3724                 break;
3725 
3726         case CKO_DATA:
3727         case CKO_CERTIFICATE:
3728         case CKO_HW_FEATURE:
3729         case CKO_VENDOR_DEFINED:
3730         default:
3731                 return (CKR_ATTRIBUTE_VALUE_INVALID);
3732         }
3733 
3734         return (rv);
3735 }
3736 
3737 
3738 /*
3739  * Get the value of a requested attribute that is common to all supported
3740  * classes (i.e. public key, private key, secret key, domain parameters,
3741  * and certificate classes).
3742  */
3743 CK_RV
3744 soft_get_common_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
3745     uchar_t object_type)
3746 {
3747 
3748         CK_RV rv = CKR_OK;
3749 
3750         switch (template->type) {
3751 
3752         case CKA_CLASS:
3753                 return (get_ulong_attr_from_object(object_p->class,
3754                     template));
3755 
3756         /* default boolean attributes */
3757         case CKA_TOKEN:
3758                 template->ulValueLen = sizeof (CK_BBOOL);
3759                 if (template->pValue == NULL) {
3760                         return (CKR_OK);
3761                 }
3762                 if (object_type & TOKEN_OBJECT)
3763                         *((CK_BBOOL *)template->pValue) = B_TRUE;
3764                 else
3765                         *((CK_BBOOL *)template->pValue) = B_FALSE;
3766                 break;
3767 
3768         case CKA_PRIVATE:
3769 
3770                 template->ulValueLen = sizeof (CK_BBOOL);
3771                 if (template->pValue == NULL) {
3772                         return (CKR_OK);
3773                 }
3774                 if (object_type & PRIVATE_OBJECT)
3775                         *((CK_BBOOL *)template->pValue) = B_TRUE;
3776                 else
3777                         *((CK_BBOOL *)template->pValue) = B_FALSE;
3778                 break;
3779 
3780         case CKA_MODIFIABLE:
3781                 template->ulValueLen = sizeof (CK_BBOOL);
3782                 if (template->pValue == NULL) {
3783                         return (CKR_OK);
3784                 }
3785                 if ((object_p->bool_attr_mask) & NOT_MODIFIABLE_BOOL_ON)
3786                         *((CK_BBOOL *)template->pValue) = B_FALSE;
3787                 else
3788                         *((CK_BBOOL *)template->pValue) = B_TRUE;
3789                 break;
3790 
3791         case CKA_LABEL:
3792                 return (get_extra_attr_from_object(object_p,
3793                     template));
3794 
3795         default:
3796                 /*
3797                  * The specified attribute for the object is invalid.
3798                  * (the object does not possess such an attribute.)
3799                  */
3800                 template->ulValueLen = (CK_ULONG)-1;
3801                 return (CKR_ATTRIBUTE_TYPE_INVALID);
3802         }
3803 
3804         return (rv);
3805 }
3806 
3807 /*
3808  * Get the value of a requested attribute that is common to all key objects
3809  * (i.e. public key, private key and secret key).
3810  */
3811 CK_RV
3812 soft_get_common_key_attrs(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
3813 {
3814 
3815         switch (template->type) {
3816 
3817         case CKA_KEY_TYPE:
3818                 return (get_ulong_attr_from_object(object_p->key_type,
3819                     template));
3820 
3821         case CKA_ID:
3822         case CKA_START_DATE:
3823         case CKA_END_DATE:
3824                 /*
3825                  * The above extra attributes have byte array type.
3826                  */
3827                 return (get_extra_attr_from_object(object_p,
3828                     template));
3829 
3830         /* Key related boolean attributes */
3831         case CKA_LOCAL:
3832                 return (get_bool_attr_from_object(object_p,
3833                     LOCAL_BOOL_ON, template));
3834 
3835         case CKA_DERIVE:
3836                 return (get_bool_attr_from_object(object_p,
3837                     DERIVE_BOOL_ON, template));
3838 
3839         case CKA_KEY_GEN_MECHANISM:
3840                 return (get_ulong_attr_from_object(object_p->mechanism,
3841                     template));
3842 
3843         default:
3844                 return (CKR_ATTRIBUTE_TYPE_INVALID);
3845         }
3846 }
3847 
3848 /*
3849  * Get the value of a requested attribute of a Public Key Object.
3850  *
3851  * Rule: All the attributes in the public key object can be revealed.
3852  */
3853 CK_RV
3854 soft_get_public_key_attribute(soft_object_t *object_p,
3855         CK_ATTRIBUTE_PTR template)
3856 {
3857 
3858         CK_RV           rv = CKR_OK;
3859         CK_KEY_TYPE     keytype = object_p->key_type;
3860 
3861         switch (template->type) {
3862 
3863         case CKA_SUBJECT:
3864         case CKA_EC_PARAMS:
3865                 /*
3866                  * The above extra attributes have byte array type.
3867                  */
3868                 return (get_extra_attr_from_object(object_p,
3869                     template));
3870 
3871         /* Key related boolean attributes */
3872         case CKA_ENCRYPT:
3873                 return (get_bool_attr_from_object(object_p,
3874                     ENCRYPT_BOOL_ON, template));
3875 
3876         case CKA_VERIFY:
3877                 return (get_bool_attr_from_object(object_p,
3878                     VERIFY_BOOL_ON, template));
3879 
3880         case CKA_VERIFY_RECOVER:
3881                 return (get_bool_attr_from_object(object_p,
3882                     VERIFY_RECOVER_BOOL_ON, template));
3883 
3884         case CKA_WRAP:
3885                 return (get_bool_attr_from_object(object_p,
3886                     WRAP_BOOL_ON, template));
3887 
3888         case CKA_TRUSTED:
3889                 return (get_bool_attr_from_object(object_p,
3890                     TRUSTED_BOOL_ON, template));
3891 
3892         case CKA_MODULUS:
3893                 /*
3894                  * This attribute is valid only for RSA public key
3895                  * object.
3896                  */
3897                 if (keytype == CKK_RSA) {
3898                         return (get_bigint_attr_from_object(
3899                             OBJ_PUB_RSA_MOD(object_p), template));
3900                 } else {
3901                         template->ulValueLen = (CK_ULONG)-1;
3902                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3903                 }
3904 
3905         case CKA_PUBLIC_EXPONENT:
3906                 if (keytype == CKK_RSA) {
3907                         return (get_bigint_attr_from_object(
3908                             OBJ_PUB_RSA_PUBEXPO(object_p), template));
3909                 } else {
3910                         template->ulValueLen = (CK_ULONG)-1;
3911                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3912                 }
3913 
3914         case CKA_MODULUS_BITS:
3915                 if (keytype == CKK_RSA) {
3916                         return (get_ulong_attr_from_object(
3917                             OBJ_PUB_RSA_MOD_BITS(object_p), template));
3918                 } else {
3919                         template->ulValueLen = (CK_ULONG)-1;
3920                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3921                 }
3922 
3923         case CKA_PRIME:
3924                 switch (keytype) {
3925                 case CKK_DSA:
3926                         return (get_bigint_attr_from_object(
3927                             OBJ_PUB_DSA_PRIME(object_p), template));
3928 
3929                 case CKK_DH:
3930                         return (get_bigint_attr_from_object(
3931                             OBJ_PUB_DH_PRIME(object_p), template));
3932 
3933                 case CKK_X9_42_DH:
3934                         return (get_bigint_attr_from_object(
3935                             OBJ_PUB_DH942_PRIME(object_p), template));
3936 
3937                 default:
3938                         template->ulValueLen = (CK_ULONG)-1;
3939                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3940                 }
3941 
3942         case CKA_SUBPRIME:
3943                 switch (keytype) {
3944                 case CKK_DSA:
3945                         return (get_bigint_attr_from_object(
3946                             OBJ_PUB_DSA_SUBPRIME(object_p), template));
3947 
3948                 case CKK_X9_42_DH:
3949                         return (get_bigint_attr_from_object(
3950                             OBJ_PUB_DH942_SUBPRIME(object_p), template));
3951 
3952                 default:
3953                         template->ulValueLen = (CK_ULONG)-1;
3954                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3955                 }
3956 
3957         case CKA_BASE:
3958                 switch (keytype) {
3959                 case CKK_DSA:
3960                         return (get_bigint_attr_from_object(
3961                             OBJ_PUB_DSA_BASE(object_p), template));
3962 
3963                 case CKK_DH:
3964                         return (get_bigint_attr_from_object(
3965                             OBJ_PUB_DH_BASE(object_p), template));
3966 
3967                 case CKK_X9_42_DH:
3968                         return (get_bigint_attr_from_object(
3969                             OBJ_PUB_DH942_BASE(object_p), template));
3970 
3971                 default:
3972                         template->ulValueLen = (CK_ULONG)-1;
3973                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3974                 }
3975 
3976         case CKA_EC_POINT:
3977                 return (get_bigint_attr_from_object(
3978                     OBJ_PUB_EC_POINT(object_p), template));
3979 
3980         case CKA_VALUE:
3981                 switch (keytype) {
3982                 case CKK_DSA:
3983                         return (get_bigint_attr_from_object(
3984                             OBJ_PUB_DSA_VALUE(object_p), template));
3985 
3986                 case CKK_DH:
3987                         return (get_bigint_attr_from_object(
3988                             OBJ_PUB_DH_VALUE(object_p), template));
3989 
3990                 case CKK_X9_42_DH:
3991                         return (get_bigint_attr_from_object(
3992                             OBJ_PUB_DH942_VALUE(object_p), template));
3993 
3994                 default:
3995                         template->ulValueLen = (CK_ULONG)-1;
3996                         return (CKR_ATTRIBUTE_TYPE_INVALID);
3997                 }
3998 
3999         default:
4000                 /*
4001                  * First, get the value of the request attribute defined
4002                  * in the list of common key attributes. If the request
4003                  * attribute is not found in that list, then get the
4004                  * attribute from the list of common attributes.
4005                  */
4006                 rv = soft_get_common_key_attrs(object_p, template);
4007                 if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4008                         rv = soft_get_common_attrs(object_p, template,
4009                             object_p->object_type);
4010                 }
4011                 break;
4012         }
4013 
4014         return (rv);
4015 }
4016 
4017 
4018 /*
4019  * Get the value of a requested attribute of a Private Key Object.
4020  *
4021  * Rule: All the attributes in the private key object can be revealed
4022  *       except those marked with footnote number "7" when the object
4023  *       has its CKA_SENSITIVE attribute set to TRUE or its
4024  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
4025  */
4026 CK_RV
4027 soft_get_private_key_attribute(soft_object_t *object_p,
4028         CK_ATTRIBUTE_PTR template)
4029 {
4030 
4031         CK_RV           rv = CKR_OK;
4032         CK_KEY_TYPE     keytype = object_p->key_type;
4033 
4034 
4035         /*
4036          * If the following specified attributes for the private key
4037          * object cannot be revealed because the object is sensitive
4038          * or unextractable, then the ulValueLen is set to -1.
4039          */
4040         if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
4041             !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4042 
4043                 switch (template->type) {
4044                 case CKA_PRIVATE_EXPONENT:
4045                 case CKA_PRIME_1:
4046                 case CKA_PRIME_2:
4047                 case CKA_EXPONENT_1:
4048                 case CKA_EXPONENT_2:
4049                 case CKA_COEFFICIENT:
4050                 case CKA_VALUE:
4051                         template->ulValueLen = (CK_ULONG)-1;
4052                         return (CKR_ATTRIBUTE_SENSITIVE);
4053                 }
4054         }
4055 
4056         switch (template->type) {
4057 
4058         case CKA_SUBJECT:
4059         case CKA_EC_PARAMS:
4060                 /*
4061                  * The above extra attributes have byte array type.
4062                  */
4063                 return (get_extra_attr_from_object(object_p,
4064                     template));
4065 
4066         /* Key related boolean attributes */
4067         case CKA_SENSITIVE:
4068                 return (get_bool_attr_from_object(object_p,
4069                     SENSITIVE_BOOL_ON, template));
4070 
4071         case CKA_SECONDARY_AUTH:
4072                 return (get_bool_attr_from_object(object_p,
4073                     SECONDARY_AUTH_BOOL_ON, template));
4074 
4075         case CKA_DECRYPT:
4076                 return (get_bool_attr_from_object(object_p,
4077                     DECRYPT_BOOL_ON, template));
4078 
4079         case CKA_SIGN:
4080                 return (get_bool_attr_from_object(object_p,
4081                     SIGN_BOOL_ON, template));
4082 
4083         case CKA_SIGN_RECOVER:
4084                 return (get_bool_attr_from_object(object_p,
4085                     SIGN_RECOVER_BOOL_ON, template));
4086 
4087         case CKA_UNWRAP:
4088                 return (get_bool_attr_from_object(object_p,
4089                     UNWRAP_BOOL_ON, template));
4090 
4091         case CKA_EXTRACTABLE:
4092                 return (get_bool_attr_from_object(object_p,
4093                     EXTRACTABLE_BOOL_ON, template));
4094 
4095         case CKA_ALWAYS_SENSITIVE:
4096                 return (get_bool_attr_from_object(object_p,
4097                     ALWAYS_SENSITIVE_BOOL_ON, template));
4098 
4099         case CKA_NEVER_EXTRACTABLE:
4100                 return (get_bool_attr_from_object(object_p,
4101                     NEVER_EXTRACTABLE_BOOL_ON, template));
4102 
4103         case CKA_MODULUS:
4104                 if (keytype == CKK_RSA) {
4105                         return (get_bigint_attr_from_object(
4106                             OBJ_PRI_RSA_MOD(object_p), template));
4107                 } else {
4108                         template->ulValueLen = (CK_ULONG)-1;
4109                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4110                         break;
4111                 }
4112 
4113         case CKA_PUBLIC_EXPONENT:
4114                 if (keytype == CKK_RSA) {
4115                         return (get_bigint_attr_from_object(
4116                             OBJ_PRI_RSA_PUBEXPO(object_p), template));
4117                 } else {
4118                         template->ulValueLen = (CK_ULONG)-1;
4119                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4120                         break;
4121                 }
4122 
4123         case CKA_PRIVATE_EXPONENT:
4124                 if (keytype == CKK_RSA) {
4125                         return (get_bigint_attr_from_object(
4126                             OBJ_PRI_RSA_PRIEXPO(object_p), template));
4127                 } else {
4128                         template->ulValueLen = (CK_ULONG)-1;
4129                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4130                         break;
4131                 }
4132 
4133         case CKA_PRIME_1:
4134                 if (keytype == CKK_RSA) {
4135                         return (get_bigint_attr_from_object(
4136                             OBJ_PRI_RSA_PRIME1(object_p), template));
4137                 } else {
4138                         template->ulValueLen = (CK_ULONG)-1;
4139                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4140                         break;
4141                 }
4142 
4143         case CKA_PRIME_2:
4144                 if (keytype == CKK_RSA) {
4145                         return (get_bigint_attr_from_object(
4146                             OBJ_PRI_RSA_PRIME2(object_p), template));
4147                 } else {
4148                         template->ulValueLen = (CK_ULONG)-1;
4149                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4150                         break;
4151                 }
4152 
4153         case CKA_EXPONENT_1:
4154                 if (keytype == CKK_RSA) {
4155                         return (get_bigint_attr_from_object(
4156                             OBJ_PRI_RSA_EXPO1(object_p), template));
4157                 } else {
4158                         template->ulValueLen = (CK_ULONG)-1;
4159                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4160                         break;
4161                 }
4162 
4163         case CKA_EXPONENT_2:
4164                 if (keytype == CKK_RSA) {
4165                         return (get_bigint_attr_from_object(
4166                             OBJ_PRI_RSA_EXPO2(object_p), template));
4167                 } else {
4168                         template->ulValueLen = (CK_ULONG)-1;
4169                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4170                         break;
4171                 }
4172 
4173         case CKA_COEFFICIENT:
4174                 if (keytype == CKK_RSA) {
4175                         return (get_bigint_attr_from_object(
4176                             OBJ_PRI_RSA_COEF(object_p), template));
4177                 } else {
4178                         template->ulValueLen = (CK_ULONG)-1;
4179                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4180                         break;
4181                 }
4182 
4183         case CKA_VALUE_BITS:
4184                 if (keytype == CKK_DH) {
4185                         return (get_ulong_attr_from_object(
4186                             OBJ_PRI_DH_VAL_BITS(object_p), template));
4187                 } else {
4188                         template->ulValueLen = (CK_ULONG)-1;
4189                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4190                         break;
4191                 }
4192 
4193         case CKA_PRIME:
4194                 switch (keytype) {
4195                 case CKK_DSA:
4196                         return (get_bigint_attr_from_object(
4197                             OBJ_PRI_DSA_PRIME(object_p), template));
4198 
4199                 case CKK_DH:
4200                         return (get_bigint_attr_from_object(
4201                             OBJ_PRI_DH_PRIME(object_p), template));
4202 
4203                 case CKK_X9_42_DH:
4204                         return (get_bigint_attr_from_object(
4205                             OBJ_PRI_DH942_PRIME(object_p), template));
4206 
4207                 default:
4208                         template->ulValueLen = (CK_ULONG)-1;
4209                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4210                 }
4211 
4212         case CKA_SUBPRIME:
4213                 switch (keytype) {
4214                 case CKK_DSA:
4215                         return (get_bigint_attr_from_object(
4216                             OBJ_PRI_DSA_SUBPRIME(object_p), template));
4217 
4218                 case CKK_X9_42_DH:
4219                         return (get_bigint_attr_from_object(
4220                             OBJ_PRI_DH942_SUBPRIME(object_p), template));
4221 
4222                 default:
4223                         template->ulValueLen = (CK_ULONG)-1;
4224                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4225                 }
4226 
4227         case CKA_BASE:
4228                 switch (keytype) {
4229                 case CKK_DSA:
4230                         return (get_bigint_attr_from_object(
4231                             OBJ_PRI_DSA_BASE(object_p), template));
4232 
4233                 case CKK_DH:
4234                         return (get_bigint_attr_from_object(
4235                             OBJ_PRI_DH_BASE(object_p), template));
4236 
4237                 case CKK_X9_42_DH:
4238                         return (get_bigint_attr_from_object(
4239                             OBJ_PRI_DH942_BASE(object_p), template));
4240 
4241                 default:
4242                         template->ulValueLen = (CK_ULONG)-1;
4243                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4244                 }
4245 
4246         case CKA_VALUE:
4247                 switch (keytype) {
4248                 case CKK_DSA:
4249                         return (get_bigint_attr_from_object(
4250                             OBJ_PRI_DSA_VALUE(object_p), template));
4251 
4252                 case CKK_DH:
4253                         return (get_bigint_attr_from_object(
4254                             OBJ_PRI_DH_VALUE(object_p), template));
4255 
4256                 case CKK_X9_42_DH:
4257                         return (get_bigint_attr_from_object(
4258                             OBJ_PRI_DH942_VALUE(object_p), template));
4259 
4260                 case CKK_EC:
4261                         return (get_bigint_attr_from_object(
4262                             OBJ_PRI_EC_VALUE(object_p), template));
4263 
4264                 default:
4265                         template->ulValueLen = (CK_ULONG)-1;
4266                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4267                 }
4268 
4269         default:
4270                 /*
4271                  * First, get the value of the request attribute defined
4272                  * in the list of common key attributes. If the request
4273                  * attribute is not found in that list, then get the
4274                  * attribute from the list of common attributes.
4275                  */
4276                 rv = soft_get_common_key_attrs(object_p, template);
4277                 if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4278                         rv = soft_get_common_attrs(object_p, template,
4279                             object_p->object_type);
4280                 }
4281                 break;
4282         }
4283 
4284         return (rv);
4285 }
4286 
4287 
4288 /*
4289  * Get the value of a requested attribute of a Secret Key Object.
4290  *
4291  * Rule: All the attributes in the secret key object can be revealed
4292  *       except those marked with footnote number "7" when the object
4293  *       has its CKA_SENSITIVE attribute set to TRUE or its
4294  *       CKA_EXTRACTABLE attribute set to FALSE (p.88 in PKCS11 spec.).
4295  */
4296 CK_RV
4297 soft_get_secret_key_attribute(soft_object_t *object_p,
4298         CK_ATTRIBUTE_PTR template)
4299 {
4300 
4301         CK_RV           rv = CKR_OK;
4302         CK_KEY_TYPE     keytype = object_p->key_type;
4303 
4304         switch (template->type) {
4305 
4306         /* Key related boolean attributes */
4307         case CKA_SENSITIVE:
4308                 return (get_bool_attr_from_object(object_p,
4309                     SENSITIVE_BOOL_ON, template));
4310 
4311         case CKA_ENCRYPT:
4312                 return (get_bool_attr_from_object(object_p,
4313                     ENCRYPT_BOOL_ON, template));
4314 
4315         case CKA_DECRYPT:
4316                 return (get_bool_attr_from_object(object_p,
4317                     DECRYPT_BOOL_ON, template));
4318 
4319         case CKA_SIGN:
4320                 return (get_bool_attr_from_object(object_p,
4321                     SIGN_BOOL_ON, template));
4322 
4323         case CKA_VERIFY:
4324                 return (get_bool_attr_from_object(object_p,
4325                     VERIFY_BOOL_ON, template));
4326 
4327         case CKA_WRAP:
4328                 return (get_bool_attr_from_object(object_p,
4329                     WRAP_BOOL_ON, template));
4330 
4331         case CKA_UNWRAP:
4332                 return (get_bool_attr_from_object(object_p,
4333                     UNWRAP_BOOL_ON, template));
4334 
4335         case CKA_EXTRACTABLE:
4336                 return (get_bool_attr_from_object(object_p,
4337                     EXTRACTABLE_BOOL_ON, template));
4338 
4339         case CKA_ALWAYS_SENSITIVE:
4340                 return (get_bool_attr_from_object(object_p,
4341                     ALWAYS_SENSITIVE_BOOL_ON, template));
4342 
4343         case CKA_NEVER_EXTRACTABLE:
4344                 return (get_bool_attr_from_object(object_p,
4345                     NEVER_EXTRACTABLE_BOOL_ON, template));
4346 
4347         case CKA_VALUE:
4348         case CKA_VALUE_LEN:
4349                 /*
4350                  * If the specified attribute for the secret key object
4351                  * cannot be revealed because the object is sensitive
4352                  * or unextractable, then the ulValueLen is set to -1.
4353                  */
4354                 if ((object_p->bool_attr_mask & SENSITIVE_BOOL_ON) ||
4355                     !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4356                         template->ulValueLen = (CK_ULONG)-1;
4357                         return (CKR_ATTRIBUTE_SENSITIVE);
4358                 }
4359 
4360                 switch (keytype) {
4361                 case CKK_RC4:
4362                 case CKK_GENERIC_SECRET:
4363                 case CKK_RC5:
4364                 case CKK_DES:
4365                 case CKK_DES2:
4366                 case CKK_DES3:
4367                 case CKK_CDMF:
4368                 case CKK_AES:
4369                 case CKK_BLOWFISH:
4370                         if (template->type == CKA_VALUE_LEN) {
4371                                 return (get_ulong_attr_from_object(
4372                                     OBJ_SEC_VALUE_LEN(object_p),
4373                                     template));
4374                         } else {
4375                                 return (get_bigint_attr_from_object(
4376                                     (biginteger_t *)OBJ_SEC(object_p),
4377                                     template));
4378                         }
4379                 default:
4380                         template->ulValueLen = (CK_ULONG)-1;
4381                         rv = CKR_ATTRIBUTE_TYPE_INVALID;
4382                         break;
4383                 }
4384                 break;
4385 
4386         default:
4387                 /*
4388                  * First, get the value of the request attribute defined
4389                  * in the list of common key attributes. If the request
4390                  * attribute is not found in that list, then get the
4391                  * attribute from the list of common attributes.
4392                  */
4393                 rv = soft_get_common_key_attrs(object_p, template);
4394                 if (rv == CKR_ATTRIBUTE_TYPE_INVALID) {
4395                         rv = soft_get_common_attrs(object_p, template,
4396                             object_p->object_type);
4397                 }
4398                 break;
4399         }
4400 
4401         return (rv);
4402 }
4403 
4404 
4405 /*
4406  * Get the value of a requested attribute of a Domain Parameters Object.
4407  *
4408  * Rule: All the attributes in the domain parameters object can be revealed.
4409  */
4410 CK_RV
4411 soft_get_domain_parameters_attribute(soft_object_t *object_p,
4412         CK_ATTRIBUTE_PTR template)
4413 {
4414 
4415         CK_RV           rv = CKR_OK;
4416         CK_KEY_TYPE     keytype = object_p->key_type;
4417 
4418         switch (template->type) {
4419 
4420         case CKA_KEY_TYPE:
4421                 return (get_ulong_attr_from_object(keytype,
4422                     template));
4423 
4424         case CKA_LOCAL:
4425                 return (get_bool_attr_from_object(object_p,
4426                     LOCAL_BOOL_ON, template));
4427 
4428         case CKA_PRIME:
4429                 switch (keytype) {
4430                 case CKK_DSA:
4431                         return (get_bigint_attr_from_object(
4432                             OBJ_DOM_DSA_PRIME(object_p), template));
4433 
4434                 case CKK_DH:
4435                         return (get_bigint_attr_from_object(
4436                             OBJ_DOM_DH_PRIME(object_p), template));
4437 
4438                 case CKK_X9_42_DH:
4439                         return (get_bigint_attr_from_object(
4440                             OBJ_DOM_DH942_PRIME(object_p), template));
4441 
4442                 default:
4443                         template->ulValueLen = (CK_ULONG)-1;
4444                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4445                 }
4446 
4447         case CKA_SUBPRIME:
4448                 switch (keytype) {
4449                 case CKK_DSA:
4450                         return (get_bigint_attr_from_object(
4451                             OBJ_DOM_DSA_SUBPRIME(object_p), template));
4452 
4453                 case CKK_X9_42_DH:
4454                         return (get_bigint_attr_from_object(
4455                             OBJ_DOM_DH942_SUBPRIME(object_p), template));
4456 
4457                 default:
4458                         template->ulValueLen = (CK_ULONG)-1;
4459                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4460                 }
4461 
4462         case CKA_BASE:
4463                 switch (keytype) {
4464                 case CKK_DSA:
4465                         return (get_bigint_attr_from_object(
4466                             OBJ_DOM_DSA_BASE(object_p), template));
4467 
4468                 case CKK_DH:
4469                         return (get_bigint_attr_from_object(
4470                             OBJ_DOM_DH_BASE(object_p), template));
4471 
4472                 case CKK_X9_42_DH:
4473                         return (get_bigint_attr_from_object(
4474                             OBJ_DOM_DH942_BASE(object_p), template));
4475 
4476                 default:
4477                         template->ulValueLen = (CK_ULONG)-1;
4478                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4479                 }
4480 
4481         case CKA_PRIME_BITS:
4482                 switch (keytype) {
4483                 case CKK_DSA:
4484                         return (get_ulong_attr_from_object(
4485                             OBJ_DOM_DSA_PRIME_BITS(object_p), template));
4486 
4487                 case CKK_DH:
4488                         return (get_ulong_attr_from_object(
4489                             OBJ_DOM_DH_PRIME_BITS(object_p), template));
4490 
4491                 case CKK_X9_42_DH:
4492                         return (get_ulong_attr_from_object(
4493                             OBJ_DOM_DH942_PRIME_BITS(object_p), template));
4494 
4495                 default:
4496                         template->ulValueLen = (CK_ULONG)-1;
4497                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4498                 }
4499 
4500         case CKA_SUB_PRIME_BITS:
4501                 switch (keytype) {
4502                 case CKK_X9_42_DH:
4503                         return (get_ulong_attr_from_object(
4504                             OBJ_DOM_DH942_SUBPRIME_BITS(object_p), template));
4505 
4506                 default:
4507                         template->ulValueLen = (CK_ULONG)-1;
4508                         return (CKR_ATTRIBUTE_TYPE_INVALID);
4509                 }
4510 
4511         default:
4512                 /*
4513                  * Get the value of a common attribute.
4514                  */
4515                 rv = soft_get_common_attrs(object_p, template,
4516                     object_p->object_type);
4517                 break;
4518         }
4519 
4520         return (rv);
4521 }
4522 
4523 /*
4524  * Get certificate attributes from an object.
4525  * return CKR_ATTRIBUTE_TYPE_INVALID if the requested type
4526  * does not exist in the certificate.
4527  */
4528 CK_RV
4529 soft_get_certificate_attribute(soft_object_t *object_p,
4530         CK_ATTRIBUTE_PTR template)
4531 {
4532         CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
4533         cert_attr_t src;
4534 
4535         switch (template->type) {
4536                 case CKA_SUBJECT:
4537                         if (certtype == CKC_X_509) {
4538                                 return (get_cert_attr_from_object(
4539                                     X509_CERT_SUBJECT(object_p), template));
4540                         }
4541                         break;
4542                 case CKA_VALUE:
4543                         if (certtype == CKC_X_509) {
4544                                 return (get_cert_attr_from_object(
4545                                     X509_CERT_VALUE(object_p), template));
4546                         } else if (certtype == CKC_X_509_ATTR_CERT) {
4547                                 return (get_cert_attr_from_object(
4548                                     X509_ATTR_CERT_VALUE(object_p), template));
4549                         }
4550                         break;
4551                 case CKA_OWNER:
4552                         if (certtype == CKC_X_509_ATTR_CERT) {
4553                                 return (get_cert_attr_from_object(
4554                                     X509_ATTR_CERT_OWNER(object_p), template));
4555                         }
4556                         break;
4557                 case CKA_CERTIFICATE_TYPE:
4558                         src.value = (CK_BYTE *)&certtype;
4559                         src.length = sizeof (certtype);
4560                         return (get_cert_attr_from_object(&src, template));
4561                 case CKA_TRUSTED:
4562                         return (get_bool_attr_from_object(object_p,
4563                             TRUSTED_BOOL_ON, template));
4564                 case CKA_ID:
4565                 case CKA_ISSUER:
4566                 case CKA_SERIAL_NUMBER:
4567                 case CKA_AC_ISSUER:
4568                 case CKA_ATTR_TYPES:
4569                         return (get_extra_attr_from_object(object_p,
4570                             template));
4571                 default:
4572                         return (soft_get_common_attrs(object_p, template,
4573                             object_p->object_type));
4574         }
4575 
4576         /*
4577          * If we got this far, then the combination of certificate type
4578          * and requested attribute is invalid.
4579          */
4580         return (CKR_ATTRIBUTE_TYPE_INVALID);
4581 }
4582 
4583 CK_RV
4584 soft_set_certificate_attribute(soft_object_t *object_p,
4585         CK_ATTRIBUTE_PTR template, boolean_t copy)
4586 {
4587         CK_CERTIFICATE_TYPE certtype = object_p->cert_type;
4588 
4589         switch (template->type) {
4590                 case CKA_SUBJECT:
4591                         if (certtype == CKC_X_509) {
4592                                 /* SUBJECT attr cannot be modified. */
4593                                 return (CKR_ATTRIBUTE_READ_ONLY);
4594                         }
4595                         break;
4596                 case CKA_OWNER:
4597                         if (certtype == CKC_X_509_ATTR_CERT) {
4598                                 /* OWNER attr cannot be modified. */
4599                                 return (CKR_ATTRIBUTE_READ_ONLY);
4600                         }
4601                         break;
4602                 case CKA_VALUE:
4603                         /* VALUE attr cannot be modified. */
4604                         return (CKR_ATTRIBUTE_READ_ONLY);
4605                 case CKA_ID:
4606                 case CKA_ISSUER:
4607                         if (certtype == CKC_X_509) {
4608                                 return (set_extra_attr_to_object(object_p,
4609                                     template->type, template));
4610                         }
4611                         break;
4612                 case CKA_AC_ISSUER:
4613                 case CKA_ATTR_TYPES:
4614                         if (certtype == CKC_X_509_ATTR_CERT) {
4615                                 return (set_extra_attr_to_object(object_p,
4616                                     template->type, template));
4617                         }
4618                         break;
4619                 case CKA_SERIAL_NUMBER:
4620                 case CKA_LABEL:
4621                         return (set_extra_attr_to_object(object_p,
4622                             template->type, template));
4623                 default:
4624                         return (soft_set_common_storage_attribute(
4625                             object_p, template, copy));
4626         }
4627 
4628         /*
4629          * If we got this far, then the combination of certificate type
4630          * and requested attribute is invalid.
4631          */
4632         return (CKR_ATTRIBUTE_TYPE_INVALID);
4633 }
4634 
4635 /*
4636  * Call the appropriate get attribute function according to the class
4637  * of object.
4638  *
4639  * The caller of this function holds the lock on the object.
4640  */
4641 CK_RV
4642 soft_get_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template)
4643 {
4644 
4645         CK_RV           rv = CKR_OK;
4646         CK_OBJECT_CLASS class = object_p->class;
4647 
4648         switch (class) {
4649         case CKO_PUBLIC_KEY:
4650                 rv = soft_get_public_key_attribute(object_p, template);
4651                 break;
4652 
4653         case CKO_PRIVATE_KEY:
4654                 rv = soft_get_private_key_attribute(object_p, template);
4655                 break;
4656 
4657         case CKO_SECRET_KEY:
4658                 rv = soft_get_secret_key_attribute(object_p, template);
4659                 break;
4660 
4661         case CKO_DOMAIN_PARAMETERS:
4662                 rv = soft_get_domain_parameters_attribute(object_p, template);
4663                 break;
4664 
4665         case CKO_CERTIFICATE:
4666                 rv = soft_get_certificate_attribute(object_p, template);
4667                 break;
4668 
4669         default:
4670                 /*
4671                  * If the specified attribute for the object is invalid
4672                  * (the object does not possess such as attribute), then
4673                  * the ulValueLen is modified to hold the value -1.
4674                  */
4675                 template->ulValueLen = (CK_ULONG)-1;
4676                 return (CKR_ATTRIBUTE_TYPE_INVALID);
4677         }
4678 
4679         return (rv);
4680 
4681 }
4682 
4683 CK_RV
4684 soft_set_common_storage_attribute(soft_object_t *object_p,
4685         CK_ATTRIBUTE_PTR template, boolean_t copy)
4686 {
4687 
4688         CK_RV rv = CKR_OK;
4689 
4690         switch (template->type) {
4691 
4692         case CKA_TOKEN:
4693                 if (copy) {
4694                         if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4695                                 if (!soft_keystore_status(KEYSTORE_INITIALIZED))
4696                                         return (CKR_DEVICE_REMOVED);
4697                                 object_p->object_type |= TOKEN_OBJECT;
4698                         }
4699                 } else {
4700                         rv = CKR_ATTRIBUTE_READ_ONLY;
4701                 }
4702 
4703                 break;
4704 
4705         case CKA_PRIVATE:
4706                 if (copy) {
4707                         if ((*(CK_BBOOL *)template->pValue) == B_TRUE) {
4708                                 (void) pthread_mutex_lock(&soft_giant_mutex);
4709                                 if (!soft_slot.authenticated) {
4710                                         /*
4711                                          * Check if this is the special case
4712                                          * when the PIN is never initialized
4713                                          * in the keystore. If true, we will
4714                                          * let it pass here and let it fail
4715                                          * with CKR_PIN_EXPIRED later on.
4716                                          */
4717                                         if (!soft_slot.userpin_change_needed) {
4718                                                 (void) pthread_mutex_unlock(
4719                                                     &soft_giant_mutex);
4720                                                 return (CKR_USER_NOT_LOGGED_IN);
4721                                         }
4722                                 }
4723                                 (void) pthread_mutex_unlock(&soft_giant_mutex);
4724                                 object_p->object_type |= PRIVATE_OBJECT;
4725                         }
4726                 } else {
4727                         rv = CKR_ATTRIBUTE_READ_ONLY;
4728                 }
4729                 break;
4730 
4731         case CKA_MODIFIABLE:
4732                 if (copy) {
4733                         if ((*(CK_BBOOL *)template->pValue) == TRUE)
4734                                 object_p->bool_attr_mask &=
4735                                     ~NOT_MODIFIABLE_BOOL_ON;
4736                         else
4737                                 object_p->bool_attr_mask |=
4738                                     NOT_MODIFIABLE_BOOL_ON;
4739                 } else {
4740                         rv = CKR_ATTRIBUTE_READ_ONLY;
4741                 }
4742                 break;
4743 
4744         case CKA_CLASS:
4745                 rv = CKR_ATTRIBUTE_READ_ONLY;
4746                 break;
4747 
4748         default:
4749                 rv = CKR_TEMPLATE_INCONSISTENT;
4750         }
4751 
4752         return (rv);
4753 }
4754 
4755 /*
4756  * Set the value of an attribute that is common to all key objects
4757  * (i.e. public key, private key and secret key).
4758  */
4759 CK_RV
4760 soft_set_common_key_attribute(soft_object_t *object_p,
4761         CK_ATTRIBUTE_PTR template, boolean_t copy)
4762 {
4763 
4764         switch (template->type) {
4765 
4766         case CKA_LABEL:
4767                 /*
4768                  * Only the LABEL can be modified in the common storage
4769                  * object attributes after the object is created.
4770                  */
4771                 return (set_extra_attr_to_object(object_p,
4772                     CKA_LABEL, template));
4773 
4774         case CKA_ID:
4775                 return (set_extra_attr_to_object(object_p,
4776                     CKA_ID, template));
4777 
4778         case CKA_START_DATE:
4779                 return (set_extra_attr_to_object(object_p,
4780                     CKA_START_DATE, template));
4781 
4782         case CKA_END_DATE:
4783                 return (set_extra_attr_to_object(object_p,
4784                     CKA_END_DATE, template));
4785 
4786         case CKA_DERIVE:
4787                 return (set_bool_attr_to_object(object_p,
4788                     DERIVE_BOOL_ON, template));
4789 
4790         case CKA_KEY_TYPE:
4791         case CKA_LOCAL:
4792         case CKA_KEY_GEN_MECHANISM:
4793                 return (CKR_ATTRIBUTE_READ_ONLY);
4794 
4795         default:
4796                 return (soft_set_common_storage_attribute(object_p,
4797                     template, copy));
4798 
4799         }
4800 
4801 }
4802 
4803 
4804 /*
4805  * Set the value of an attribute of a Public Key Object.
4806  *
4807  * Rule: The attributes marked with footnote number "8" in the PKCS11
4808  *       spec may be modified (p.88 in PKCS11 spec.).
4809  */
4810 CK_RV
4811 soft_set_public_key_attribute(soft_object_t *object_p,
4812         CK_ATTRIBUTE_PTR template, boolean_t copy)
4813 {
4814         CK_KEY_TYPE     keytype = object_p->key_type;
4815 
4816         switch (template->type) {
4817 
4818         case CKA_SUBJECT:
4819                 return (set_extra_attr_to_object(object_p,
4820                     CKA_SUBJECT, template));
4821 
4822         case CKA_ENCRYPT:
4823                 return (set_bool_attr_to_object(object_p,
4824                     ENCRYPT_BOOL_ON, template));
4825 
4826         case CKA_VERIFY:
4827                 return (set_bool_attr_to_object(object_p,
4828                     VERIFY_BOOL_ON, template));
4829 
4830         case CKA_VERIFY_RECOVER:
4831                 return (set_bool_attr_to_object(object_p,
4832                     VERIFY_RECOVER_BOOL_ON, template));
4833 
4834         case CKA_WRAP:
4835                 return (set_bool_attr_to_object(object_p,
4836                     WRAP_BOOL_ON, template));
4837 
4838         case CKA_MODULUS:
4839         case CKA_MODULUS_BITS:
4840         case CKA_PUBLIC_EXPONENT:
4841                 if (keytype == CKK_RSA)
4842                         return (CKR_ATTRIBUTE_READ_ONLY);
4843                 break;
4844 
4845         case CKA_SUBPRIME:
4846                 if ((keytype == CKK_DSA) ||
4847                     (keytype == CKK_X9_42_DH))
4848                         return (CKR_ATTRIBUTE_READ_ONLY);
4849                 break;
4850 
4851         case CKA_PRIME:
4852         case CKA_BASE:
4853         case CKA_VALUE:
4854                 if ((keytype == CKK_DSA) ||
4855                     (keytype == CKK_DH) ||
4856                     (keytype == CKK_X9_42_DH))
4857                         return (CKR_ATTRIBUTE_READ_ONLY);
4858                 break;
4859 
4860         default:
4861                 /*
4862                  * Set the value of a common key attribute.
4863                  */
4864                 return (soft_set_common_key_attribute(object_p,
4865                     template, copy));
4866 
4867         }
4868         /*
4869          * If we got this far, then the combination of key type
4870          * and requested attribute is invalid.
4871          */
4872         return (CKR_ATTRIBUTE_TYPE_INVALID);
4873 }
4874 
4875 
4876 /*
4877  * Set the value of an attribute of a Private Key Object.
4878  *
4879  * Rule: The attributes marked with footnote number "8" in the PKCS11
4880  *       spec may be modified (p.88 in PKCS11 spec.).
4881  */
4882 CK_RV
4883 soft_set_private_key_attribute(soft_object_t *object_p,
4884         CK_ATTRIBUTE_PTR template, boolean_t copy)
4885 {
4886         CK_KEY_TYPE     keytype = object_p->key_type;
4887 
4888         switch (template->type) {
4889 
4890         case CKA_SUBJECT:
4891                 return (set_extra_attr_to_object(object_p,
4892                     CKA_SUBJECT, template));
4893 
4894         case CKA_SENSITIVE:
4895                 /*
4896                  * Cannot set SENSITIVE to FALSE if it is already ON.
4897                  */
4898                 if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
4899                     (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
4900                         return (CKR_ATTRIBUTE_READ_ONLY);
4901                 }
4902 
4903                 if (*(CK_BBOOL *)template->pValue)
4904                         object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
4905                 return (CKR_OK);
4906 
4907         case CKA_DECRYPT:
4908                 return (set_bool_attr_to_object(object_p,
4909                     DECRYPT_BOOL_ON, template));
4910 
4911         case CKA_SIGN:
4912                 return (set_bool_attr_to_object(object_p,
4913                     SIGN_BOOL_ON, template));
4914 
4915         case CKA_SIGN_RECOVER:
4916                 return (set_bool_attr_to_object(object_p,
4917                     SIGN_RECOVER_BOOL_ON, template));
4918 
4919         case CKA_UNWRAP:
4920                 return (set_bool_attr_to_object(object_p,
4921                     UNWRAP_BOOL_ON, template));
4922 
4923         case CKA_EXTRACTABLE:
4924                 /*
4925                  * Cannot set EXTRACTABLE to TRUE if it is already OFF.
4926                  */
4927                 if ((*(CK_BBOOL *)template->pValue) &&
4928                     !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
4929                         return (CKR_ATTRIBUTE_READ_ONLY);
4930                 }
4931 
4932                 if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
4933                         object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
4934                 return (CKR_OK);
4935 
4936         case CKA_MODULUS:
4937         case CKA_PUBLIC_EXPONENT:
4938         case CKA_PRIVATE_EXPONENT:
4939         case CKA_PRIME_1:
4940         case CKA_PRIME_2:
4941         case CKA_EXPONENT_1:
4942         case CKA_EXPONENT_2:
4943         case CKA_COEFFICIENT:
4944                 if (keytype == CKK_RSA) {
4945                         return (CKR_ATTRIBUTE_READ_ONLY);
4946                 }
4947                 break;
4948 
4949         case CKA_SUBPRIME:
4950                 if ((keytype == CKK_DSA) ||
4951                     (keytype == CKK_X9_42_DH))
4952                         return (CKR_ATTRIBUTE_READ_ONLY);
4953                 break;
4954 
4955         case CKA_PRIME:
4956         case CKA_BASE:
4957         case CKA_VALUE:
4958                 if ((keytype == CKK_DSA) ||
4959                     (keytype == CKK_DH) ||
4960                     (keytype == CKK_X9_42_DH))
4961                         return (CKR_ATTRIBUTE_READ_ONLY);
4962                 break;
4963 
4964         case CKA_VALUE_BITS:
4965                 if (keytype == CKK_DH)
4966                         return (CKR_ATTRIBUTE_READ_ONLY);
4967                 break;
4968 
4969         default:
4970                 /*
4971                  * Set the value of a common key attribute.
4972                  */
4973                 return (soft_set_common_key_attribute(object_p,
4974                     template, copy));
4975         }
4976 
4977         /*
4978          * If we got this far, then the combination of key type
4979          * and requested attribute is invalid.
4980          */
4981         return (CKR_ATTRIBUTE_TYPE_INVALID);
4982 }
4983 
4984 /*
4985  * Set the value of an attribute of a Secret Key Object.
4986  *
4987  * Rule: The attributes marked with footnote number "8" in the PKCS11
4988  *       spec may be modified (p.88 in PKCS11 spec.).
4989  */
4990 CK_RV
4991 soft_set_secret_key_attribute(soft_object_t *object_p,
4992         CK_ATTRIBUTE_PTR template, boolean_t copy)
4993 {
4994         CK_KEY_TYPE     keytype = object_p->key_type;
4995 
4996         switch (template->type) {
4997 
4998         case CKA_SENSITIVE:
4999                 /*
5000                  * Cannot set SENSITIVE to FALSE if it is already ON.
5001                  */
5002                 if (((*(CK_BBOOL *)template->pValue) == B_FALSE) &&
5003                     (object_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
5004                         return (CKR_ATTRIBUTE_READ_ONLY);
5005                 }
5006 
5007                 if (*(CK_BBOOL *)template->pValue)
5008                         object_p->bool_attr_mask |= SENSITIVE_BOOL_ON;
5009                 return (CKR_OK);
5010 
5011         case CKA_ENCRYPT:
5012                 return (set_bool_attr_to_object(object_p,
5013                     ENCRYPT_BOOL_ON, template));
5014 
5015         case CKA_DECRYPT:
5016                 return (set_bool_attr_to_object(object_p,
5017                     DECRYPT_BOOL_ON, template));
5018 
5019         case CKA_SIGN:
5020                 return (set_bool_attr_to_object(object_p,
5021                     SIGN_BOOL_ON, template));
5022 
5023         case CKA_VERIFY:
5024                 return (set_bool_attr_to_object(object_p,
5025                     VERIFY_BOOL_ON, template));
5026 
5027         case CKA_WRAP:
5028                 return (set_bool_attr_to_object(object_p,
5029                     WRAP_BOOL_ON, template));
5030 
5031         case CKA_UNWRAP:
5032                 return (set_bool_attr_to_object(object_p,
5033                     UNWRAP_BOOL_ON, template));
5034 
5035         case CKA_EXTRACTABLE:
5036                 /*
5037                  * Cannot set EXTRACTABLE to TRUE if it is already OFF.
5038                  */
5039                 if ((*(CK_BBOOL *)template->pValue) &&
5040                     !(object_p->bool_attr_mask & EXTRACTABLE_BOOL_ON)) {
5041                         return (CKR_ATTRIBUTE_READ_ONLY);
5042                 }
5043 
5044                 if ((*(CK_BBOOL *)template->pValue) == B_FALSE)
5045                         object_p->bool_attr_mask &= ~EXTRACTABLE_BOOL_ON;
5046                 return (CKR_OK);
5047 
5048         case CKA_VALUE:
5049                 return (CKR_ATTRIBUTE_READ_ONLY);
5050 
5051         case CKA_VALUE_LEN:
5052                 if ((keytype == CKK_RC4) ||
5053                     (keytype == CKK_GENERIC_SECRET) ||
5054                     (keytype == CKK_AES) ||
5055                     (keytype == CKK_BLOWFISH))
5056                         return (CKR_ATTRIBUTE_READ_ONLY);
5057                 break;
5058 
5059         default:
5060                 /*
5061                  * Set the value of a common key attribute.
5062                  */
5063                 return (soft_set_common_key_attribute(object_p,
5064                     template, copy));
5065 
5066         }
5067         /*
5068          * If we got this far, then the combination of key type
5069          * and requested attribute is invalid.
5070          */
5071         return (CKR_ATTRIBUTE_TYPE_INVALID);
5072 }
5073 
5074 
5075 /*
5076  * Call the appropriate set attribute function according to the class
5077  * of object.
5078  *
5079  * The caller of this function does not hold the lock on the original
5080  * object, since this function is setting the attribute on the new object
5081  * that is being modified.
5082  *
5083  * Argument copy: TRUE when called by C_CopyObject,
5084  *                FALSE when called by C_SetAttributeValue.
5085  */
5086 CK_RV
5087 soft_set_attribute(soft_object_t *object_p, CK_ATTRIBUTE_PTR template,
5088     boolean_t copy)
5089 {
5090 
5091         CK_RV           rv = CKR_OK;
5092         CK_OBJECT_CLASS class = object_p->class;
5093 
5094         switch (class) {
5095 
5096         case CKO_PUBLIC_KEY:
5097                 rv = soft_set_public_key_attribute(object_p, template, copy);
5098                 break;
5099 
5100         case CKO_PRIVATE_KEY:
5101                 rv = soft_set_private_key_attribute(object_p, template, copy);
5102                 break;
5103 
5104         case CKO_SECRET_KEY:
5105                 rv = soft_set_secret_key_attribute(object_p, template, copy);
5106                 break;
5107 
5108         case CKO_DOMAIN_PARAMETERS:
5109                 switch (template->type) {
5110                 case CKA_LABEL:
5111                         /*
5112                          * Only the LABEL can be modified in the common
5113                          * storage object attributes after the object is
5114                          * created.
5115                          */
5116                         return (set_extra_attr_to_object(object_p,
5117                             CKA_LABEL, template));
5118                 default:
5119                         return (CKR_TEMPLATE_INCONSISTENT);
5120                 }
5121         case CKO_CERTIFICATE:
5122                 rv = soft_set_certificate_attribute(object_p, template, copy);
5123                 break;
5124 
5125         default:
5126                 /*
5127                  * If the template specifies a value of an attribute
5128                  * which is incompatible with other existing attributes
5129                  * of the object, then fails with return code
5130                  * CKR_TEMPLATE_INCONSISTENT.
5131                  */
5132                 rv = CKR_TEMPLATE_INCONSISTENT;
5133                 break;
5134         }
5135 
5136         return (rv);
5137 }
5138 
5139 CK_RV
5140 soft_get_public_value(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
5141     uchar_t *value, uint32_t *value_len)
5142 {
5143         uint32_t len = 0;
5144         switch (type) {
5145 
5146         /* The following attributes belong to RSA */
5147         case CKA_MODULUS:
5148 #ifdef  __sparcv9
5149                 len =
5150                     /* LINTED */
5151                     (uint32_t)
5152                     ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
5153 #else   /* !__sparcv9 */
5154                 len =
5155                     ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value_len;
5156 #endif  /* __sparcv9 */
5157 
5158                 /* This attribute MUST BE set */
5159                 if (len == 0 || len > *value_len) {
5160                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5161                 }
5162                 *value_len = len;
5163 
5164                 (void) memcpy(value,
5165                     ((biginteger_t *)OBJ_PUB_RSA_MOD(key))->big_value,
5166                     *value_len);
5167 
5168                 break;
5169 
5170         case CKA_PUBLIC_EXPONENT:
5171 #ifdef  __sparcv9
5172                 len =
5173                     /* LINTED */
5174                     (uint32_t)
5175                     ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5176 #else   /* !__sparcv9 */
5177                 len =
5178                     ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value_len;
5179 #endif  /* __sparcv9 */
5180 
5181                 /* This attribute MUST BE set */
5182                 if (len == 0 || len > *value_len) {
5183                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5184                 }
5185                 *value_len = len;
5186 
5187                 (void) memcpy(value,
5188                     ((biginteger_t *)OBJ_PUB_RSA_PUBEXPO(key))->big_value,
5189                     *value_len);
5190 
5191                 break;
5192 
5193         /* The following attributes belong to DSA and DH */
5194         case CKA_PRIME:
5195 
5196                 if (key->key_type == CKK_DSA)
5197 #ifdef  __sparcv9
5198                         len =
5199                             /* LINTED */
5200                             (uint32_t)
5201                             ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5202                             big_value_len;
5203 #else   /* !__sparcv9 */
5204                         len =
5205                             ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->
5206                             big_value_len;
5207 #endif  /* __sparcv9 */
5208                 else
5209 #ifdef  __sparcv9
5210                         len =
5211                             /* LINTED */
5212                             (uint32_t)
5213                             ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5214                             big_value_len;
5215 #else   /* !__sparcv9 */
5216                         len =
5217                             ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->
5218                             big_value_len;
5219 #endif  /* __sparcv9 */
5220 
5221                 /* This attribute MUST BE set */
5222                 if (len == 0 || len > *value_len) {
5223                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5224                 }
5225                 *value_len = len;
5226 
5227                 if (key->key_type == CKK_DSA)
5228                         (void) memcpy(value,
5229                             ((biginteger_t *)OBJ_PUB_DSA_PRIME(key))->big_value,
5230                             *value_len);
5231                 else
5232                         (void) memcpy(value,
5233                             ((biginteger_t *)OBJ_PUB_DH_PRIME(key))->big_value,
5234                             *value_len);
5235 
5236                 break;
5237 
5238         case CKA_SUBPRIME:
5239 #ifdef  __sparcv9
5240                 len =
5241                     /* LINTED */
5242                     (uint32_t)
5243                     ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5244 #else   /* !__sparcv9 */
5245                 len =
5246                     ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value_len;
5247 #endif  /* __sparcv9 */
5248 
5249                 /* This attribute MUST BE set */
5250                 if (len == 0 || len > *value_len) {
5251                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5252                 }
5253                 *value_len = len;
5254 
5255                 (void) memcpy(value,
5256                     ((biginteger_t *)OBJ_PUB_DSA_SUBPRIME(key))->big_value,
5257                     *value_len);
5258 
5259                 break;
5260 
5261         case CKA_BASE:
5262 
5263                 if (key->key_type == CKK_DSA)
5264 #ifdef  __sparcv9
5265                         len =
5266                             /* LINTED */
5267                             (uint32_t)
5268                             ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5269                             big_value_len;
5270 #else   /* !__sparcv9 */
5271                         len =
5272                             ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->
5273                             big_value_len;
5274 #endif  /* __sparcv9 */
5275                 else
5276 #ifdef  __sparcv9
5277                         len =
5278                             /* LINTED */
5279                             (uint32_t)
5280                             ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5281                             big_value_len;
5282 #else   /* !__sparcv9 */
5283                         len =
5284                             ((biginteger_t *)OBJ_PUB_DH_BASE(key))->
5285                             big_value_len;
5286 #endif  /* __sparcv9 */
5287 
5288                 /* This attribute MUST BE set */
5289                 if (len == 0 || len > *value_len) {
5290                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5291                 }
5292                 *value_len = len;
5293 
5294                 if (key->key_type == CKK_DSA)
5295                         (void) memcpy(value,
5296                             ((biginteger_t *)OBJ_PUB_DSA_BASE(key))->big_value,
5297                             *value_len);
5298                 else
5299                         (void) memcpy(value,
5300                             ((biginteger_t *)OBJ_PUB_DH_BASE(key))->big_value,
5301                             *value_len);
5302                 break;
5303 
5304         case CKA_VALUE:
5305 
5306                 if (key->key_type == CKK_DSA)
5307 #ifdef  __sparcv9
5308                         len =
5309                             /* LINTED */
5310                             (uint32_t)
5311                             ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5312                             big_value_len;
5313 #else   /* !__sparcv9 */
5314                         len =
5315                             ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->
5316                             big_value_len;
5317 #endif  /* __sparcv9 */
5318                 else
5319 #ifdef  __sparcv9
5320                         len =
5321                             /* LINTED */
5322                             (uint32_t)
5323                             ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5324                             big_value_len;
5325 #else   /* !__sparcv9 */
5326                         len =
5327                             ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->
5328                             big_value_len;
5329 #endif  /* __sparcv9 */
5330 
5331                 /* This attribute MUST BE set */
5332                 if (len == 0 || len > *value_len) {
5333                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5334                 }
5335                 *value_len = len;
5336 
5337                 if (key->key_type == CKK_DSA)
5338                         (void) memcpy(value,
5339                             ((biginteger_t *)OBJ_PUB_DSA_VALUE(key))->big_value,
5340                             *value_len);
5341                 else
5342                         (void) memcpy(value,
5343                             ((biginteger_t *)OBJ_PUB_DH_VALUE(key))->big_value,
5344                             *value_len);
5345 
5346                 break;
5347         }
5348 
5349         return (CKR_OK);
5350 }
5351 
5352 
5353 CK_RV
5354 soft_get_private_value(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
5355     uchar_t *value, uint32_t *value_len)
5356 {
5357 
5358         uint32_t len = 0;
5359 
5360         switch (type) {
5361 
5362         /* The following attributes belong to RSA */
5363         case CKA_MODULUS:
5364 #ifdef  __sparcv9
5365                 len =
5366                     /* LINTED */
5367                     (uint32_t)
5368                     ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5369 #else   /* !__sparcv9 */
5370                 len =
5371                     ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value_len;
5372 #endif  /* __sparcv9 */
5373 
5374                 /* This attribute MUST BE set */
5375                 if (len == 0 || len > *value_len) {
5376                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5377                 }
5378                 *value_len = len;
5379 
5380                 (void) memcpy(value,
5381                     ((biginteger_t *)OBJ_PRI_RSA_MOD(key))->big_value,
5382                     *value_len);
5383 
5384                 break;
5385 
5386         case CKA_PRIVATE_EXPONENT:
5387 #ifdef  __sparcv9
5388                 len =
5389                     /* LINTED */
5390                     (uint32_t)
5391                     ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5392 #else   /* !__sparcv9 */
5393                 len =
5394                     ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value_len;
5395 #endif  /* __sparcv9 */
5396 
5397                 /* This attribute MUST BE set */
5398                 if (len == 0 || len > *value_len) {
5399                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5400                 }
5401                 *value_len = len;
5402 
5403                 (void) memcpy(value,
5404                     ((biginteger_t *)OBJ_PRI_RSA_PRIEXPO(key))->big_value,
5405                     *value_len);
5406 
5407                 break;
5408 
5409         case CKA_PRIME_1:
5410 #ifdef  __sparcv9
5411                 len =
5412                     /* LINTED */
5413                     (uint32_t)
5414                     ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5415 #else   /* !__sparcv9 */
5416                 len =
5417                     ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value_len;
5418 #endif  /* __sparcv9 */
5419 
5420                 if (len > *value_len) {
5421                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5422                 }
5423                 *value_len = len;
5424 
5425                 if (*value_len == 0) {
5426                         return (CKR_OK);
5427                 }
5428 
5429                 (void) memcpy(value,
5430                     ((biginteger_t *)OBJ_PRI_RSA_PRIME1(key))->big_value,
5431                     *value_len);
5432 
5433                 break;
5434 
5435         case CKA_PRIME_2:
5436 #ifdef  __sparcv9
5437                 len =
5438                     /* LINTED */
5439                     (uint32_t)
5440                     ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5441 #else   /* !__sparcv9 */
5442                 len =
5443                     ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value_len;
5444 #endif  /* __sparcv9 */
5445 
5446                 if (len > *value_len) {
5447                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5448                 }
5449                 *value_len = len;
5450 
5451                 if (*value_len == 0) {
5452                         return (CKR_OK);
5453                 }
5454 
5455                 (void) memcpy(value,
5456                     ((biginteger_t *)OBJ_PRI_RSA_PRIME2(key))->big_value,
5457                     *value_len);
5458 
5459                 break;
5460 
5461         case CKA_EXPONENT_1:
5462 #ifdef  __sparcv9
5463                 len =
5464                     /* LINTED */
5465                     (uint32_t)
5466                     ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5467 #else   /* !__sparcv9 */
5468                 len =
5469                     ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value_len;
5470 #endif  /* __sparcv9 */
5471 
5472                 if (len > *value_len) {
5473                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5474                 }
5475                 *value_len = len;
5476 
5477                 if (*value_len == 0) {
5478                         return (CKR_OK);
5479                 }
5480 
5481                 (void) memcpy(value,
5482                     ((biginteger_t *)OBJ_PRI_RSA_EXPO1(key))->big_value,
5483                     *value_len);
5484 
5485                 break;
5486 
5487         case CKA_EXPONENT_2:
5488 #ifdef  __sparcv9
5489                 len =
5490                     /* LINTED */
5491                     (uint32_t)
5492                     ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5493 #else   /* !__sparcv9 */
5494                 len =
5495                     ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value_len;
5496 #endif  /* __sparcv9 */
5497 
5498                 if (len > *value_len) {
5499                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5500                 }
5501                 *value_len = len;
5502 
5503                 if (*value_len == 0) {
5504                         return (CKR_OK);
5505                 }
5506 
5507                 (void) memcpy(value,
5508                     ((biginteger_t *)OBJ_PRI_RSA_EXPO2(key))->big_value,
5509                     *value_len);
5510 
5511                 break;
5512 
5513         case CKA_COEFFICIENT:
5514 #ifdef  __sparcv9
5515                 len =
5516                     /* LINTED */
5517                     (uint32_t)
5518                     ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5519 #else   /* !__sparcv9 */
5520                 len =
5521                     ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value_len;
5522 #endif  /* __sparcv9 */
5523 
5524                 if (len > *value_len) {
5525                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5526                 }
5527                 *value_len = len;
5528 
5529                 if (*value_len == 0) {
5530                         return (CKR_OK);
5531                 }
5532 
5533                 (void) memcpy(value,
5534                     ((biginteger_t *)OBJ_PRI_RSA_COEF(key))->big_value,
5535                     *value_len);
5536 
5537                 break;
5538 
5539         /* The following attributes belong to DSA and DH */
5540         case CKA_PRIME:
5541 
5542                 if (key->key_type == CKK_DSA)
5543 #ifdef  __sparcv9
5544                         len =
5545                             /* LINTED */
5546                             (uint32_t)
5547                             ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5548                             big_value_len;
5549 #else   /* !__sparcv9 */
5550                         len =
5551                             ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->
5552                             big_value_len;
5553 #endif  /* __sparcv9 */
5554                 else
5555 #ifdef  __sparcv9
5556                         len =
5557                             /* LINTED */
5558                             (uint32_t)
5559                             ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5560                             big_value_len;
5561 #else   /* !__sparcv9 */
5562                         len =
5563                             ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->
5564                             big_value_len;
5565 #endif  /* __sparcv9 */
5566 
5567                 /* This attribute MUST BE set */
5568                 if (len == 0 || len > *value_len) {
5569                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5570                 }
5571                 *value_len = len;
5572 
5573                 if (key->key_type == CKK_DSA)
5574                         (void) memcpy(value,
5575                             ((biginteger_t *)OBJ_PRI_DSA_PRIME(key))->big_value,
5576                             *value_len);
5577                 else
5578                         (void) memcpy(value,
5579                             ((biginteger_t *)OBJ_PRI_DH_PRIME(key))->big_value,
5580                             *value_len);
5581 
5582                 break;
5583 
5584         case CKA_SUBPRIME:
5585 #ifdef  __sparcv9
5586                 len =
5587                     /* LINTED */
5588                     (uint32_t)
5589                     ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5590 #else   /* !__sparcv9 */
5591                 len =
5592                     ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value_len;
5593 #endif  /* __sparcv9 */
5594 
5595                 /* This attribute MUST BE set */
5596                 if (len == 0 || len > *value_len) {
5597                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5598                 }
5599                 *value_len = len;
5600 
5601                 (void) memcpy(value,
5602                     ((biginteger_t *)OBJ_PRI_DSA_SUBPRIME(key))->big_value,
5603                     *value_len);
5604 
5605                 break;
5606 
5607         case CKA_BASE:
5608 
5609                 if (key->key_type == CKK_DSA)
5610 #ifdef  __sparcv9
5611                         len =
5612                             /* LINTED */
5613                             (uint32_t)
5614                             ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5615                             big_value_len;
5616 #else   /* !__sparcv9 */
5617                         len =
5618                             ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->
5619                             big_value_len;
5620 #endif  /* __sparcv9 */
5621                 else
5622 #ifdef  __sparcv9
5623                         len =
5624                             /* LINTED */
5625                             (uint32_t)
5626                             ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5627                             big_value_len;
5628 #else   /* !__sparcv9 */
5629                         len =
5630                             ((biginteger_t *)OBJ_PRI_DH_BASE(key))->
5631                             big_value_len;
5632 #endif  /* __sparcv9 */
5633 
5634                 /* This attribute MUST BE set */
5635                 if (len == 0 || len > *value_len) {
5636                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5637                 }
5638                 *value_len = len;
5639 
5640                 if (key->key_type == CKK_DSA)
5641                         (void) memcpy(value,
5642                             ((biginteger_t *)OBJ_PRI_DSA_BASE(key))->big_value,
5643                             *value_len);
5644                 else
5645                         (void) memcpy(value,
5646                             ((biginteger_t *)OBJ_PRI_DH_BASE(key))->big_value,
5647                             *value_len);
5648                 break;
5649 
5650         case CKA_VALUE:
5651 
5652                 if (key->key_type == CKK_DSA) {
5653 #ifdef  __sparcv9
5654                         len =
5655                             /* LINTED */
5656                             (uint32_t)
5657                             ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5658                             big_value_len;
5659 #else   /* !__sparcv9 */
5660                         len =
5661                             ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->
5662                             big_value_len;
5663 #endif  /* __sparcv9 */
5664                 } else if (key->key_type == CKK_DH) {
5665 #ifdef  __sparcv9
5666                         len =
5667                             /* LINTED */
5668                             (uint32_t)
5669                             ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5670                             big_value_len;
5671 #else   /* !__sparcv9 */
5672                         len =
5673                             ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->
5674                             big_value_len;
5675 #endif  /* __sparcv9 */
5676                 } else {
5677 #ifdef  __sparcv9
5678                         len =
5679                             /* LINTED */
5680                             (uint32_t)
5681                             ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->
5682                             big_value_len;
5683 #else   /* !__sparcv9 */
5684                         len =
5685                             ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->
5686                             big_value_len;
5687 #endif  /* __sparcv9 */
5688                 }
5689 
5690                 /* This attribute MUST BE set */
5691                 if (len == 0 || len > *value_len) {
5692                         return (CKR_ATTRIBUTE_VALUE_INVALID);
5693                 }
5694                 *value_len = len;
5695 
5696                 if (key->key_type == CKK_DSA) {
5697                         (void) memcpy(value,
5698                             ((biginteger_t *)OBJ_PRI_DSA_VALUE(key))->big_value,
5699                             *value_len);
5700                 } else if (key->key_type == CKK_DH) {
5701                         (void) memcpy(value,
5702                             ((biginteger_t *)OBJ_PRI_DH_VALUE(key))->big_value,
5703                             *value_len);
5704                 } else {
5705                         (void) memcpy(value,
5706                             ((biginteger_t *)OBJ_PRI_EC_VALUE(key))->big_value,
5707                             *value_len);
5708                 }
5709 
5710                 break;
5711         }
5712 
5713         return (CKR_OK);
5714 
5715 }
5716 
5717 static CK_RV
5718 copy_bigint(biginteger_t *new_bigint, biginteger_t *old_bigint)
5719 {
5720         new_bigint->big_value =
5721             malloc((sizeof (CK_BYTE) * new_bigint->big_value_len));
5722 
5723         if (new_bigint->big_value == NULL) {
5724                 return (CKR_HOST_MEMORY);
5725         }
5726 
5727         (void) memcpy(new_bigint->big_value, old_bigint->big_value,
5728             (sizeof (CK_BYTE) * new_bigint->big_value_len));
5729 
5730         return (CKR_OK);
5731 }
5732 
5733 static void
5734 free_public_key_attr(public_key_obj_t *pbk, CK_KEY_TYPE key_type)
5735 {
5736         if (pbk == NULL) {
5737                 return;
5738         }
5739 
5740         switch (key_type) {
5741                 case CKK_RSA:
5742                         bigint_attr_cleanup(KEY_PUB_RSA_MOD(pbk));
5743                         bigint_attr_cleanup(KEY_PUB_RSA_PUBEXPO(pbk));
5744                         break;
5745                 case CKK_DSA:
5746                         bigint_attr_cleanup(KEY_PUB_DSA_PRIME(pbk));
5747                         bigint_attr_cleanup(KEY_PUB_DSA_SUBPRIME(pbk));
5748                         bigint_attr_cleanup(KEY_PUB_DSA_BASE(pbk));
5749                         bigint_attr_cleanup(KEY_PUB_DSA_VALUE(pbk));
5750                         break;
5751                 case CKK_DH:
5752                         bigint_attr_cleanup(KEY_PUB_DH_PRIME(pbk));
5753                         bigint_attr_cleanup(KEY_PUB_DH_BASE(pbk));
5754                         bigint_attr_cleanup(KEY_PUB_DH_VALUE(pbk));
5755                         break;
5756                 case CKK_EC:
5757                         bigint_attr_cleanup(KEY_PUB_EC_POINT(pbk));
5758                         break;
5759                 case CKK_X9_42_DH:
5760                         bigint_attr_cleanup(KEY_PUB_DH942_PRIME(pbk));
5761                         bigint_attr_cleanup(KEY_PUB_DH942_SUBPRIME(pbk));
5762                         bigint_attr_cleanup(KEY_PUB_DH942_BASE(pbk));
5763                         bigint_attr_cleanup(KEY_PUB_DH942_VALUE(pbk));
5764                         break;
5765                 default:
5766                         break;
5767         }
5768         free(pbk);
5769 }
5770 
5771 CK_RV
5772 soft_copy_public_key_attr(public_key_obj_t *old_pub_key_obj_p,
5773     public_key_obj_t **new_pub_key_obj_p, CK_KEY_TYPE key_type)
5774 {
5775 
5776         public_key_obj_t *pbk;
5777         CK_RV rv = CKR_OK;
5778 
5779         pbk = calloc(1, sizeof (public_key_obj_t));
5780         if (pbk == NULL) {
5781                 return (CKR_HOST_MEMORY);
5782         }
5783 
5784         switch (key_type) {
5785                 case CKK_RSA:
5786                         (void) memcpy(KEY_PUB_RSA(pbk),
5787                             KEY_PUB_RSA(old_pub_key_obj_p),
5788                             sizeof (rsa_pub_key_t));
5789                         /* copy modulus */
5790                         rv = copy_bigint(KEY_PUB_RSA_MOD(pbk),
5791                             KEY_PUB_RSA_MOD(old_pub_key_obj_p));
5792                         if (rv != CKR_OK) {
5793                                 free_public_key_attr(pbk, key_type);
5794                                 return (rv);
5795                         }
5796                         /* copy public exponent */
5797                         rv = copy_bigint(KEY_PUB_RSA_PUBEXPO(pbk),
5798                             KEY_PUB_RSA_PUBEXPO(old_pub_key_obj_p));
5799                         if (rv != CKR_OK) {
5800                                 free_public_key_attr(pbk, key_type);
5801                                 return (rv);
5802                         }
5803                         break;
5804                 case CKK_DSA:
5805                         (void) memcpy(KEY_PUB_DSA(pbk),
5806                             KEY_PUB_DSA(old_pub_key_obj_p),
5807                             sizeof (dsa_pub_key_t));
5808 
5809                         /* copy prime */
5810                         rv = copy_bigint(KEY_PUB_DSA_PRIME(pbk),
5811                             KEY_PUB_DSA_PRIME(old_pub_key_obj_p));
5812                         if (rv != CKR_OK) {
5813                                 free_public_key_attr(pbk, key_type);
5814                                 return (rv);
5815                         }
5816 
5817                         /* copy subprime */
5818                         rv = copy_bigint(KEY_PUB_DSA_SUBPRIME(pbk),
5819                             KEY_PUB_DSA_SUBPRIME(old_pub_key_obj_p));
5820                         if (rv != CKR_OK) {
5821                                 free_public_key_attr(pbk, key_type);
5822                                 return (rv);
5823                         }
5824 
5825                         /* copy base */
5826                         rv = copy_bigint(KEY_PUB_DSA_BASE(pbk),
5827                             KEY_PUB_DSA_BASE(old_pub_key_obj_p));
5828                         if (rv != CKR_OK) {
5829                                 free_public_key_attr(pbk, key_type);
5830                                 return (rv);
5831                         }
5832 
5833                         /* copy value */
5834                         rv = copy_bigint(KEY_PUB_DSA_VALUE(pbk),
5835                             KEY_PUB_DSA_VALUE(old_pub_key_obj_p));
5836                         if (rv != CKR_OK) {
5837                                 free_public_key_attr(pbk, key_type);
5838                                 return (rv);
5839                         }
5840                         break;
5841                 case CKK_DH:
5842                         (void) memcpy(KEY_PUB_DH(pbk),
5843                             KEY_PUB_DH(old_pub_key_obj_p),
5844                             sizeof (dh_pub_key_t));
5845 
5846                         /* copy prime */
5847                         rv = copy_bigint(KEY_PUB_DH_PRIME(pbk),
5848                             KEY_PUB_DH_PRIME(old_pub_key_obj_p));
5849                         if (rv != CKR_OK) {
5850                                 free_public_key_attr(pbk, key_type);
5851                                 return (rv);
5852                         }
5853 
5854                         /* copy base */
5855                         rv = copy_bigint(KEY_PUB_DH_BASE(pbk),
5856                             KEY_PUB_DH_BASE(old_pub_key_obj_p));
5857                         if (rv != CKR_OK) {
5858                                 free_public_key_attr(pbk, key_type);
5859                                 return (rv);
5860                         }
5861 
5862                         /* copy value */
5863                         rv = copy_bigint(KEY_PUB_DH_VALUE(pbk),
5864                             KEY_PUB_DH_VALUE(old_pub_key_obj_p));
5865                         if (rv != CKR_OK) {
5866                                 free_public_key_attr(pbk, key_type);
5867                                 return (rv);
5868                         }
5869                         break;
5870                 case CKK_EC:
5871                         (void) memcpy(KEY_PUB_EC(pbk),
5872                             KEY_PUB_EC(old_pub_key_obj_p),
5873                             sizeof (ec_pub_key_t));
5874 
5875                         /* copy point */
5876                         rv = copy_bigint(KEY_PUB_EC_POINT(pbk),
5877                             KEY_PUB_EC_POINT(old_pub_key_obj_p));
5878                         if (rv != CKR_OK) {
5879                                 free_public_key_attr(pbk, key_type);
5880                                 return (rv);
5881                         }
5882                         break;
5883                 case CKK_X9_42_DH:
5884                         (void) memcpy(KEY_PUB_DH942(pbk),
5885                             KEY_PUB_DH942(old_pub_key_obj_p),
5886                             sizeof (dh942_pub_key_t));
5887 
5888                         /* copy prime */
5889                         rv = copy_bigint(KEY_PUB_DH942_PRIME(pbk),
5890                             KEY_PUB_DH942_PRIME(old_pub_key_obj_p));
5891                         if (rv != CKR_OK) {
5892                                 free_public_key_attr(pbk, key_type);
5893                                 return (rv);
5894                         }
5895 
5896                         /* copy subprime */
5897                         rv = copy_bigint(KEY_PUB_DH942_SUBPRIME(pbk),
5898                             KEY_PUB_DH942_SUBPRIME(old_pub_key_obj_p));
5899                         if (rv != CKR_OK) {
5900                                 free_public_key_attr(pbk, key_type);
5901                                 return (rv);
5902                         }
5903 
5904                         /* copy base */
5905                         rv = copy_bigint(KEY_PUB_DH942_BASE(pbk),
5906                             KEY_PUB_DH942_BASE(old_pub_key_obj_p));
5907                         if (rv != CKR_OK) {
5908                                 free_public_key_attr(pbk, key_type);
5909                                 return (rv);
5910                         }
5911 
5912                         /* copy value */
5913                         rv = copy_bigint(KEY_PUB_DH942_VALUE(pbk),
5914                             KEY_PUB_DH942_VALUE(old_pub_key_obj_p));
5915                         if (rv != CKR_OK) {
5916                                 free_public_key_attr(pbk, key_type);
5917                                 return (rv);
5918                         }
5919                         break;
5920                 default:
5921                         break;
5922         }
5923         *new_pub_key_obj_p = pbk;
5924         return (rv);
5925 }
5926 
5927 static void
5928 free_private_key_attr(private_key_obj_t *pbk, CK_KEY_TYPE key_type)
5929 {
5930         if (pbk == NULL) {
5931                 return;
5932         }
5933 
5934         switch (key_type) {
5935                 case CKK_RSA:
5936                         bigint_attr_cleanup(KEY_PRI_RSA_MOD(pbk));
5937                         bigint_attr_cleanup(KEY_PRI_RSA_PUBEXPO(pbk));
5938                         bigint_attr_cleanup(KEY_PRI_RSA_PRIEXPO(pbk));
5939                         bigint_attr_cleanup(KEY_PRI_RSA_PRIME1(pbk));
5940                         bigint_attr_cleanup(KEY_PRI_RSA_PRIME2(pbk));
5941                         bigint_attr_cleanup(KEY_PRI_RSA_EXPO1(pbk));
5942                         bigint_attr_cleanup(KEY_PRI_RSA_EXPO2(pbk));
5943                         bigint_attr_cleanup(KEY_PRI_RSA_COEF(pbk));
5944                         break;
5945                 case CKK_DSA:
5946                         bigint_attr_cleanup(KEY_PRI_DSA_PRIME(pbk));
5947                         bigint_attr_cleanup(KEY_PRI_DSA_SUBPRIME(pbk));
5948                         bigint_attr_cleanup(KEY_PRI_DSA_BASE(pbk));
5949                         bigint_attr_cleanup(KEY_PRI_DSA_VALUE(pbk));
5950                         break;
5951                 case CKK_DH:
5952                         bigint_attr_cleanup(KEY_PRI_DH_PRIME(pbk));
5953                         bigint_attr_cleanup(KEY_PRI_DH_BASE(pbk));
5954                         bigint_attr_cleanup(KEY_PRI_DH_VALUE(pbk));
5955                         break;
5956                 case CKK_EC:
5957                         bigint_attr_cleanup(KEY_PRI_EC_VALUE(pbk));
5958                         break;
5959                 case CKK_X9_42_DH:
5960                         bigint_attr_cleanup(KEY_PRI_DH942_PRIME(pbk));
5961                         bigint_attr_cleanup(KEY_PRI_DH942_SUBPRIME(pbk));
5962                         bigint_attr_cleanup(KEY_PRI_DH942_BASE(pbk));
5963                         bigint_attr_cleanup(KEY_PRI_DH942_VALUE(pbk));
5964                         break;
5965                 default:
5966                         break;
5967         }
5968         free(pbk);
5969 }
5970 
5971 CK_RV
5972 soft_copy_private_key_attr(private_key_obj_t *old_pri_key_obj_p,
5973     private_key_obj_t **new_pri_key_obj_p, CK_KEY_TYPE key_type)
5974 {
5975         CK_RV rv = CKR_OK;
5976         private_key_obj_t *pbk;
5977 
5978         pbk = calloc(1, sizeof (private_key_obj_t));
5979         if (pbk == NULL) {
5980                 return (CKR_HOST_MEMORY);
5981         }
5982 
5983         switch (key_type) {
5984                 case CKK_RSA:
5985                         (void) memcpy(KEY_PRI_RSA(pbk),
5986                             KEY_PRI_RSA(old_pri_key_obj_p),
5987                             sizeof (rsa_pri_key_t));
5988                         /* copy modulus */
5989                         rv = copy_bigint(KEY_PRI_RSA_MOD(pbk),
5990                             KEY_PRI_RSA_MOD(old_pri_key_obj_p));
5991                         if (rv != CKR_OK) {
5992                                 free_private_key_attr(pbk, key_type);
5993                                 return (rv);
5994                         }
5995                         /* copy public exponent */
5996                         rv = copy_bigint(KEY_PRI_RSA_PUBEXPO(pbk),
5997                             KEY_PRI_RSA_PUBEXPO(old_pri_key_obj_p));
5998                         if (rv != CKR_OK) {
5999                                 free_private_key_attr(pbk, key_type);
6000                                 return (rv);
6001                         }
6002                         /* copy private exponent */
6003                         rv = copy_bigint(KEY_PRI_RSA_PRIEXPO(pbk),
6004                             KEY_PRI_RSA_PRIEXPO(old_pri_key_obj_p));
6005                         if (rv != CKR_OK) {
6006                                 free_private_key_attr(pbk, key_type);
6007                                 return (rv);
6008                         }
6009                         /* copy prime_1 */
6010                         rv = copy_bigint(KEY_PRI_RSA_PRIME1(pbk),
6011                             KEY_PRI_RSA_PRIME1(old_pri_key_obj_p));
6012                         if (rv != CKR_OK) {
6013                                 free_private_key_attr(pbk, key_type);
6014                                 return (rv);
6015                         }
6016                         /* copy prime_2 */
6017                         rv = copy_bigint(KEY_PRI_RSA_PRIME2(pbk),
6018                             KEY_PRI_RSA_PRIME2(old_pri_key_obj_p));
6019                         if (rv != CKR_OK) {
6020                                 free_private_key_attr(pbk, key_type);
6021                                 return (rv);
6022                         }
6023                         /* copy exponent_1 */
6024                         rv = copy_bigint(KEY_PRI_RSA_EXPO1(pbk),
6025                             KEY_PRI_RSA_EXPO1(old_pri_key_obj_p));
6026                         if (rv != CKR_OK) {
6027                                 free_private_key_attr(pbk, key_type);
6028                                 return (rv);
6029                         }
6030                         /* copy exponent_2 */
6031                         rv = copy_bigint(KEY_PRI_RSA_EXPO2(pbk),
6032                             KEY_PRI_RSA_EXPO2(old_pri_key_obj_p));
6033                         if (rv != CKR_OK) {
6034                                 free_private_key_attr(pbk, key_type);
6035                                 return (rv);
6036                         }
6037                         /* copy coefficient */
6038                         rv = copy_bigint(KEY_PRI_RSA_COEF(pbk),
6039                             KEY_PRI_RSA_COEF(old_pri_key_obj_p));
6040                         if (rv != CKR_OK) {
6041                                 free_private_key_attr(pbk, key_type);
6042                                 return (rv);
6043                         }
6044                         break;
6045                 case CKK_DSA:
6046                         (void) memcpy(KEY_PRI_DSA(pbk),
6047                             KEY_PRI_DSA(old_pri_key_obj_p),
6048                             sizeof (dsa_pri_key_t));
6049 
6050                         /* copy prime */
6051                         rv = copy_bigint(KEY_PRI_DSA_PRIME(pbk),
6052                             KEY_PRI_DSA_PRIME(old_pri_key_obj_p));
6053                         if (rv != CKR_OK) {
6054                                 free_private_key_attr(pbk, key_type);
6055                                 return (rv);
6056                         }
6057 
6058                         /* copy subprime */
6059                         rv = copy_bigint(KEY_PRI_DSA_SUBPRIME(pbk),
6060                             KEY_PRI_DSA_SUBPRIME(old_pri_key_obj_p));
6061                         if (rv != CKR_OK) {
6062                                 free_private_key_attr(pbk, key_type);
6063                                 return (rv);
6064                         }
6065 
6066                         /* copy base */
6067                         rv = copy_bigint(KEY_PRI_DSA_BASE(pbk),
6068                             KEY_PRI_DSA_BASE(old_pri_key_obj_p));
6069                         if (rv != CKR_OK) {
6070                                 free_private_key_attr(pbk, key_type);
6071                                 return (rv);
6072                         }
6073 
6074                         /* copy value */
6075                         rv = copy_bigint(KEY_PRI_DSA_VALUE(pbk),
6076                             KEY_PRI_DSA_VALUE(old_pri_key_obj_p));
6077                         if (rv != CKR_OK) {
6078                                 free_private_key_attr(pbk, key_type);
6079                                 return (rv);
6080                         }
6081                         break;
6082                 case CKK_DH:
6083                         (void) memcpy(KEY_PRI_DH(pbk),
6084                             KEY_PRI_DH(old_pri_key_obj_p),
6085                             sizeof (dh_pri_key_t));
6086 
6087                         /* copy prime */
6088                         rv = copy_bigint(KEY_PRI_DH_PRIME(pbk),
6089                             KEY_PRI_DH_PRIME(old_pri_key_obj_p));
6090                         if (rv != CKR_OK) {
6091                                 free_private_key_attr(pbk, key_type);
6092                                 return (rv);
6093                         }
6094 
6095                         /* copy base */
6096                         rv = copy_bigint(KEY_PRI_DH_BASE(pbk),
6097                             KEY_PRI_DH_BASE(old_pri_key_obj_p));
6098                         if (rv != CKR_OK) {
6099                                 free_private_key_attr(pbk, key_type);
6100                                 return (rv);
6101                         }
6102 
6103                         /* copy value */
6104                         rv = copy_bigint(KEY_PRI_DH_VALUE(pbk),
6105                             KEY_PRI_DH_VALUE(old_pri_key_obj_p));
6106                         if (rv != CKR_OK) {
6107                                 free_private_key_attr(pbk, key_type);
6108                                 return (rv);
6109                         }
6110                         break;
6111                 case CKK_EC:
6112                         (void) memcpy(KEY_PRI_EC(pbk),
6113                             KEY_PRI_EC(old_pri_key_obj_p),
6114                             sizeof (ec_pri_key_t));
6115 
6116                         /* copy value */
6117                         rv = copy_bigint(KEY_PRI_EC_VALUE(pbk),
6118                             KEY_PRI_EC_VALUE(old_pri_key_obj_p));
6119                         if (rv != CKR_OK) {
6120                                 free_private_key_attr(pbk, key_type);
6121                                 return (rv);
6122                         }
6123                         break;
6124                 case CKK_X9_42_DH:
6125                         (void) memcpy(KEY_PRI_DH942(pbk),
6126                             KEY_PRI_DH942(old_pri_key_obj_p),
6127                             sizeof (dh942_pri_key_t));
6128 
6129                         /* copy prime */
6130                         rv = copy_bigint(KEY_PRI_DH942_PRIME(pbk),
6131                             KEY_PRI_DH942_PRIME(old_pri_key_obj_p));
6132                         if (rv != CKR_OK) {
6133                                 free_private_key_attr(pbk, key_type);
6134                                 return (rv);
6135                         }
6136 
6137                         /* copy subprime */
6138                         rv = copy_bigint(KEY_PRI_DH942_SUBPRIME(pbk),
6139                             KEY_PRI_DH942_SUBPRIME(old_pri_key_obj_p));
6140                         if (rv != CKR_OK) {
6141                                 free_private_key_attr(pbk, key_type);
6142                                 return (rv);
6143                         }
6144 
6145                         /* copy base */
6146                         rv = copy_bigint(KEY_PRI_DH942_BASE(pbk),
6147                             KEY_PRI_DH942_BASE(old_pri_key_obj_p));
6148                         if (rv != CKR_OK) {
6149                                 free_private_key_attr(pbk, key_type);
6150                                 return (rv);
6151                         }
6152 
6153                         /* copy value */
6154                         rv = copy_bigint(KEY_PRI_DH942_VALUE(pbk),
6155                             KEY_PRI_DH942_VALUE(old_pri_key_obj_p));
6156                         if (rv != CKR_OK) {
6157                                 free_private_key_attr(pbk, key_type);
6158                                 return (rv);
6159                         }
6160                         break;
6161                 default:
6162                         break;
6163         }
6164         *new_pri_key_obj_p = pbk;
6165         return (rv);
6166 }
6167 
6168 static void
6169 free_domain_attr(domain_obj_t *domain, CK_KEY_TYPE key_type)
6170 {
6171         if (domain == NULL) {
6172                 return;
6173         }
6174 
6175         switch (key_type) {
6176                 case CKK_DSA:
6177                         bigint_attr_cleanup(KEY_DOM_DSA_PRIME(domain));
6178                         bigint_attr_cleanup(KEY_DOM_DSA_SUBPRIME(domain));
6179                         bigint_attr_cleanup(KEY_DOM_DSA_BASE(domain));
6180                         break;
6181                 case CKK_DH:
6182                         bigint_attr_cleanup(KEY_DOM_DH_PRIME(domain));
6183                         bigint_attr_cleanup(KEY_DOM_DH_BASE(domain));
6184                         break;
6185                 case CKK_X9_42_DH:
6186                         bigint_attr_cleanup(KEY_DOM_DH942_PRIME(domain));
6187                         bigint_attr_cleanup(KEY_DOM_DH942_SUBPRIME(domain));
6188                         bigint_attr_cleanup(KEY_DOM_DH942_BASE(domain));
6189                         break;
6190                 default:
6191                         break;
6192         }
6193         free(domain);
6194 }
6195 
6196 CK_RV
6197 soft_copy_domain_attr(domain_obj_t *old_domain_obj_p,
6198     domain_obj_t **new_domain_obj_p, CK_KEY_TYPE key_type)
6199 {
6200         CK_RV rv = CKR_OK;
6201         domain_obj_t *domain;
6202 
6203         domain = calloc(1, sizeof (domain_obj_t));
6204         if (domain == NULL) {
6205                 return (CKR_HOST_MEMORY);
6206         }
6207 
6208         switch (key_type) {
6209                 case CKK_DSA:
6210                         (void) memcpy(KEY_DOM_DSA(domain),
6211                             KEY_DOM_DSA(old_domain_obj_p),
6212                             sizeof (dsa_dom_key_t));
6213 
6214                         /* copy prime */
6215                         rv = copy_bigint(KEY_DOM_DSA_PRIME(domain),
6216                             KEY_DOM_DSA_PRIME(old_domain_obj_p));
6217                         if (rv != CKR_OK) {
6218                                 free_domain_attr(domain, key_type);
6219                                 return (rv);
6220                         }
6221 
6222                         /* copy subprime */
6223                         rv = copy_bigint(KEY_DOM_DSA_SUBPRIME(domain),
6224                             KEY_DOM_DSA_SUBPRIME(old_domain_obj_p));
6225                         if (rv != CKR_OK) {
6226                                 free_domain_attr(domain, key_type);
6227                                 return (rv);
6228                         }
6229 
6230                         /* copy base */
6231                         rv = copy_bigint(KEY_DOM_DSA_BASE(domain),
6232                             KEY_DOM_DSA_BASE(old_domain_obj_p));
6233                         if (rv != CKR_OK) {
6234                                 free_domain_attr(domain, key_type);
6235                                 return (rv);
6236                         }
6237 
6238                         break;
6239                 case CKK_DH:
6240                         (void) memcpy(KEY_DOM_DH(domain),
6241                             KEY_DOM_DH(old_domain_obj_p),
6242                             sizeof (dh_dom_key_t));
6243 
6244                         /* copy prime */
6245                         rv = copy_bigint(KEY_DOM_DH_PRIME(domain),
6246                             KEY_DOM_DH_PRIME(old_domain_obj_p));
6247                         if (rv != CKR_OK) {
6248                                 free_domain_attr(domain, key_type);
6249                                 return (rv);
6250                         }
6251 
6252                         /* copy base */
6253                         rv = copy_bigint(KEY_DOM_DH_BASE(domain),
6254                             KEY_DOM_DH_BASE(old_domain_obj_p));
6255                         if (rv != CKR_OK) {
6256                                 free_domain_attr(domain, key_type);
6257                                 return (rv);
6258                         }
6259 
6260                         break;
6261                 case CKK_X9_42_DH:
6262                         (void) memcpy(KEY_DOM_DH942(domain),
6263                             KEY_DOM_DH942(old_domain_obj_p),
6264                             sizeof (dh942_dom_key_t));
6265 
6266                         /* copy prime */
6267                         rv = copy_bigint(KEY_DOM_DH942_PRIME(domain),
6268                             KEY_DOM_DH942_PRIME(old_domain_obj_p));
6269                         if (rv != CKR_OK) {
6270                                 free_domain_attr(domain, key_type);
6271                                 return (rv);
6272                         }
6273 
6274                         /* copy subprime */
6275                         rv = copy_bigint(KEY_DOM_DH942_SUBPRIME(domain),
6276                             KEY_DOM_DH942_SUBPRIME(old_domain_obj_p));
6277                         if (rv != CKR_OK) {
6278                                 free_domain_attr(domain, key_type);
6279                                 return (rv);
6280                         }
6281 
6282                         /* copy base */
6283                         rv = copy_bigint(KEY_DOM_DH942_BASE(domain),
6284                             KEY_DOM_DH942_BASE(old_domain_obj_p));
6285                         if (rv != CKR_OK) {
6286                                 free_domain_attr(domain, key_type);
6287                                 return (rv);
6288                         }
6289 
6290                         break;
6291                 default:
6292                         break;
6293         }
6294         *new_domain_obj_p = domain;
6295         return (rv);
6296 }
6297 
6298 CK_RV
6299 soft_copy_secret_key_attr(secret_key_obj_t *old_secret_key_obj_p,
6300     secret_key_obj_t **new_secret_key_obj_p)
6301 {
6302         secret_key_obj_t *sk;
6303 
6304         sk = malloc(sizeof (secret_key_obj_t));
6305         if (sk == NULL) {
6306                 return (CKR_HOST_MEMORY);
6307         }
6308         (void) memcpy(sk, old_secret_key_obj_p, sizeof (secret_key_obj_t));
6309 
6310         /* copy the secret key value */
6311         sk->sk_value = malloc(sk->sk_value_len);
6312         if (sk->sk_value == NULL) {
6313                 free(sk);
6314                 return (CKR_HOST_MEMORY);
6315         }
6316         (void) memcpy(sk->sk_value, old_secret_key_obj_p->sk_value,
6317             (sizeof (CK_BYTE) * sk->sk_value_len));
6318 
6319         /*
6320          * Copy the pre-expanded key schedule.
6321          */
6322         if (old_secret_key_obj_p->key_sched != NULL &&
6323             old_secret_key_obj_p->keysched_len > 0) {
6324                 sk->key_sched = malloc(old_secret_key_obj_p->keysched_len);
6325                 if (sk->key_sched == NULL) {
6326                         freezero(sk->sk_value, sk->sk_value_len);
6327                         free(sk);
6328                         return (CKR_HOST_MEMORY);
6329                 }
6330                 sk->keysched_len = old_secret_key_obj_p->keysched_len;
6331                 (void) memcpy(sk->key_sched, old_secret_key_obj_p->key_sched,
6332                     sk->keysched_len);
6333         }
6334 
6335         *new_secret_key_obj_p = sk;
6336 
6337         return (CKR_OK);
6338 }
6339 
6340 /*
6341  * If CKA_CLASS not given, guess CKA_CLASS using
6342  * attributes on template .
6343  *
6344  * Some attributes are specific to an object class.  If one or more
6345  * of these attributes are in the template, make a list of classes
6346  * that can have these attributes.  This would speed up the search later,
6347  * because we can immediately skip an object if the class of that
6348  * object can not possibly contain one of the attributes.
6349  *
6350  */
6351 void
6352 soft_process_find_attr(CK_OBJECT_CLASS *pclasses,
6353     CK_ULONG *num_result_pclasses, CK_ATTRIBUTE_PTR pTemplate,
6354     CK_ULONG ulCount)
6355 {
6356         ulong_t i;
6357         int j;
6358         boolean_t pub_found = B_FALSE,
6359             priv_found = B_FALSE,
6360             secret_found = B_FALSE,
6361             domain_found = B_FALSE,
6362             hardware_found = B_FALSE,
6363             cert_found = B_FALSE;
6364         int num_pub_key_attrs, num_priv_key_attrs,
6365             num_secret_key_attrs, num_domain_attrs,
6366             num_hardware_attrs, num_cert_attrs;
6367         int num_pclasses = 0;
6368 
6369         for (i = 0; i < ulCount; i++) {
6370                 if (pTemplate[i].type == CKA_CLASS) {
6371                         /*
6372                          * don't need to guess the class, it is specified.
6373                          * Just record the class, and return.
6374                          */
6375                         pclasses[0] =
6376                             (*((CK_OBJECT_CLASS *)pTemplate[i].pValue));
6377                         *num_result_pclasses = 1;
6378                         return;
6379                 }
6380         }
6381 
6382         num_pub_key_attrs =
6383             sizeof (PUB_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6384         num_priv_key_attrs =
6385             sizeof (PRIV_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6386         num_secret_key_attrs =
6387             sizeof (SECRET_KEY_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6388         num_domain_attrs =
6389             sizeof (DOMAIN_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6390         num_hardware_attrs =
6391             sizeof (HARDWARE_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6392         num_cert_attrs =
6393             sizeof (CERT_ATTRS) / sizeof (CK_ATTRIBUTE_TYPE);
6394 
6395         /*
6396          * Get the list of objects class that might contain
6397          * some attributes.
6398          */
6399         for (i = 0; i < ulCount; i++) {
6400                 /*
6401                  * only check if this attribute can belong to public key object
6402                  * class if public key object isn't already in the list
6403                  */
6404                 if (!pub_found) {
6405                         for (j = 0; j < num_pub_key_attrs; j++) {
6406                                 if (pTemplate[i].type == PUB_KEY_ATTRS[j]) {
6407                                         pub_found = B_TRUE;
6408                                         pclasses[num_pclasses++] =
6409                                             CKO_PUBLIC_KEY;
6410                                         break;
6411                                 }
6412                         }
6413                 }
6414 
6415                 if (!priv_found) {
6416                         for (j = 0; j < num_priv_key_attrs; j++) {
6417                                 if (pTemplate[i].type == PRIV_KEY_ATTRS[j]) {
6418                                         priv_found = B_TRUE;
6419                                         pclasses[num_pclasses++] =
6420                                             CKO_PRIVATE_KEY;
6421                                         break;
6422                                 }
6423                         }
6424                 }
6425 
6426                 if (!secret_found) {
6427                         for (j = 0; j < num_secret_key_attrs; j++) {
6428                                 if (pTemplate[i].type == SECRET_KEY_ATTRS[j]) {
6429                                         secret_found = B_TRUE;
6430                                         pclasses[num_pclasses++] =
6431                                             CKO_SECRET_KEY;
6432                                         break;
6433                                 }
6434                         }
6435                 }
6436 
6437                 if (!domain_found) {
6438                         for (j = 0; j < num_domain_attrs; j++) {
6439                                 if (pTemplate[i].type == DOMAIN_ATTRS[j]) {
6440                                         domain_found = B_TRUE;
6441                                         pclasses[num_pclasses++] =
6442                                             CKO_DOMAIN_PARAMETERS;
6443                                         break;
6444                                 }
6445                         }
6446                 }
6447 
6448                 if (!hardware_found) {
6449                         for (j = 0; j < num_hardware_attrs; j++) {
6450                                 if (pTemplate[i].type == HARDWARE_ATTRS[j]) {
6451                                         hardware_found = B_TRUE;
6452                                         pclasses[num_pclasses++] =
6453                                             CKO_HW_FEATURE;
6454                                         break;
6455                                 }
6456                         }
6457                 }
6458 
6459                 if (!cert_found) {
6460                         for (j = 0; j < num_cert_attrs; j++) {
6461                                 if (pTemplate[i].type == CERT_ATTRS[j]) {
6462                                         cert_found = B_TRUE;
6463                                         pclasses[num_pclasses++] =
6464                                             CKO_CERTIFICATE;
6465                                         break;
6466                                 }
6467                         }
6468                 }
6469         }
6470         *num_result_pclasses = num_pclasses;
6471 }
6472 
6473 boolean_t
6474 soft_find_match_attrs(soft_object_t *obj, CK_OBJECT_CLASS *pclasses,
6475     CK_ULONG num_pclasses, CK_ATTRIBUTE *template, CK_ULONG num_attr)
6476 {
6477         ulong_t i;
6478         CK_ATTRIBUTE *tmpl_attr, *obj_attr;
6479         cert_attr_t *cert_attr;
6480         uint64_t attr_mask;
6481         biginteger_t *bigint;
6482         boolean_t compare_attr, compare_bigint, compare_boolean;
6483         boolean_t compare_cert_val, compare_cert_type;
6484 
6485         /*
6486          * Check if the class of this object match with any
6487          * of object classes that can possibly contain the
6488          * requested attributes.
6489          */
6490         if (num_pclasses > 0) {
6491                 for (i = 0; i < num_pclasses; i++) {
6492                         if (obj->class == pclasses[i]) {
6493                                 break;
6494                         }
6495                 }
6496                 if (i == num_pclasses) {
6497                         /*
6498                          * this object can't possibly contain one or
6499                          * more attributes, don't need to check this object
6500                          */
6501                         return (B_FALSE);
6502                 }
6503         }
6504 
6505         /* need to examine everything */
6506         for (i = 0; i < num_attr; i++) {
6507                 tmpl_attr = &(template[i]);
6508                 compare_attr = B_FALSE;
6509                 compare_bigint = B_FALSE;
6510                 compare_boolean = B_FALSE;
6511                 compare_cert_val = B_FALSE;
6512                 compare_cert_type = B_FALSE;
6513                 switch (tmpl_attr->type) {
6514                 /* First, check the most common attributes */
6515                 case CKA_CLASS:
6516                         if (*((CK_OBJECT_CLASS *)tmpl_attr->pValue) !=
6517                             obj->class) {
6518                                 return (B_FALSE);
6519                         }
6520                         break;
6521                 case CKA_KEY_TYPE:
6522                         if (*((CK_KEY_TYPE *)tmpl_attr->pValue) !=
6523                             obj->key_type) {
6524                                 return (B_FALSE);
6525                         }
6526                         break;
6527                 case CKA_ENCRYPT:
6528                         attr_mask = (obj->bool_attr_mask) & ENCRYPT_BOOL_ON;
6529                         compare_boolean = B_TRUE;
6530                         break;
6531                 case CKA_DECRYPT:
6532                         attr_mask = (obj->bool_attr_mask) & DECRYPT_BOOL_ON;
6533                         compare_boolean = B_TRUE;
6534                         break;
6535                 case CKA_WRAP:
6536                         attr_mask = (obj->bool_attr_mask) & WRAP_BOOL_ON;
6537                         compare_boolean = B_TRUE;
6538                         break;
6539                 case CKA_UNWRAP:
6540                         attr_mask = (obj->bool_attr_mask) & UNWRAP_BOOL_ON;
6541                         compare_boolean = B_TRUE;
6542                         break;
6543                 case CKA_SIGN:
6544                         attr_mask = (obj->bool_attr_mask) & SIGN_BOOL_ON;
6545                         compare_boolean = B_TRUE;
6546                         break;
6547                 case CKA_SIGN_RECOVER:
6548                         attr_mask = (obj->bool_attr_mask) &
6549                             SIGN_RECOVER_BOOL_ON;
6550                         compare_boolean = B_TRUE;
6551                         break;
6552                 case CKA_VERIFY:
6553                         attr_mask = (obj->bool_attr_mask) & VERIFY_BOOL_ON;
6554                         compare_boolean = B_TRUE;
6555                         break;
6556                 case CKA_VERIFY_RECOVER:
6557                         attr_mask = (obj->bool_attr_mask) &
6558                             VERIFY_RECOVER_BOOL_ON;
6559                         compare_boolean = B_TRUE;
6560                         break;
6561                 case CKA_DERIVE:
6562                         attr_mask = (obj->bool_attr_mask) & DERIVE_BOOL_ON;
6563                         compare_boolean = B_TRUE;
6564                         break;
6565                 case CKA_LOCAL:
6566                         attr_mask = (obj->bool_attr_mask) & LOCAL_BOOL_ON;
6567                         compare_boolean = B_TRUE;
6568                         break;
6569                 case CKA_SENSITIVE:
6570                         attr_mask = (obj->bool_attr_mask) & SENSITIVE_BOOL_ON;
6571                         compare_boolean = B_TRUE;
6572                         break;
6573                 case CKA_SECONDARY_AUTH:
6574                         attr_mask = (obj->bool_attr_mask) &
6575                             SECONDARY_AUTH_BOOL_ON;
6576                         compare_boolean = B_TRUE;
6577                         break;
6578                 case CKA_TRUSTED:
6579                         attr_mask = (obj->bool_attr_mask) & TRUSTED_BOOL_ON;
6580                         compare_boolean = B_TRUE;
6581                         break;
6582                 case CKA_EXTRACTABLE:
6583                         attr_mask = (obj->bool_attr_mask) &
6584                             EXTRACTABLE_BOOL_ON;
6585                         compare_boolean = B_TRUE;
6586                         break;
6587                 case CKA_ALWAYS_SENSITIVE:
6588                         attr_mask = (obj->bool_attr_mask) &
6589                             ALWAYS_SENSITIVE_BOOL_ON;
6590                         compare_boolean = B_TRUE;
6591                         break;
6592                 case CKA_NEVER_EXTRACTABLE:
6593                         attr_mask = (obj->bool_attr_mask) &
6594                             NEVER_EXTRACTABLE_BOOL_ON;
6595                         compare_boolean = B_TRUE;
6596                         break;
6597                 case CKA_TOKEN:
6598                         attr_mask = (obj->object_type) & TOKEN_OBJECT;
6599                         compare_boolean = B_TRUE;
6600                         break;
6601                 case CKA_PRIVATE:
6602                         attr_mask = (obj->object_type) & PRIVATE_OBJECT;
6603                         compare_boolean = B_TRUE;
6604                         break;
6605                 case CKA_MODIFIABLE:
6606                 {
6607                         CK_BBOOL bval;
6608                         attr_mask = (obj->bool_attr_mask) &
6609                             NOT_MODIFIABLE_BOOL_ON;
6610 
6611                         if (attr_mask) {
6612                                 bval = FALSE;
6613                         } else {
6614                                 bval = TRUE;
6615                         }
6616                         if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
6617                                 return (B_FALSE);
6618                         }
6619                         break;
6620                 }
6621                 case CKA_OWNER:
6622                         /*
6623                          * For X.509 attribute certificate object, get its
6624                          * CKA_OWNER attribute from the x509_attr_cert_t struct.
6625                          */
6626                         if ((obj->class == CKO_CERTIFICATE) &&
6627                             (obj->cert_type == CKC_X_509_ATTR_CERT)) {
6628                                 cert_attr = X509_ATTR_CERT_OWNER(obj);
6629                                 compare_cert_val = B_TRUE;
6630                         }
6631                         break;
6632                 case CKA_SUBJECT:
6633                         /*
6634                          * For X.509 certificate object, get its CKA_SUBJECT
6635                          * attribute from the x509_cert_t struct (not from
6636                          * the extra_attrlistp).
6637                          */
6638                         if ((obj->class == CKO_CERTIFICATE) &&
6639                             (obj->cert_type == CKC_X_509)) {
6640                                 cert_attr = X509_CERT_SUBJECT(obj);
6641                                 compare_cert_val = B_TRUE;
6642                                 break;
6643                         }
6644                         /*FALLTHRU*/
6645                 case CKA_ID:
6646                 case CKA_START_DATE:
6647                 case CKA_END_DATE:
6648                 case CKA_KEY_GEN_MECHANISM:
6649                 case CKA_LABEL:
6650                 case CKA_ISSUER:
6651                 case CKA_SERIAL_NUMBER:
6652                 case CKA_AC_ISSUER:
6653                 case CKA_ATTR_TYPES:
6654                         /* find these attributes from extra_attrlistp */
6655                         obj_attr = get_extra_attr(tmpl_attr->type, obj);
6656                         compare_attr = B_TRUE;
6657                         break;
6658                 case CKA_CERTIFICATE_TYPE:
6659                         compare_cert_type = B_TRUE;
6660                         break;
6661                 case CKA_VALUE_LEN:
6662                         /* only secret key has this attribute */
6663                         if (obj->class == CKO_SECRET_KEY) {
6664                                 if (*((CK_ULONG *)tmpl_attr->pValue) !=
6665                                     OBJ_SEC_VALUE_LEN(obj)) {
6666                                         return (B_FALSE);
6667                                 }
6668                         } else {
6669                                 return (B_FALSE);
6670                         }
6671                         break;
6672                 case CKA_VALUE:
6673                         switch (obj->class) {
6674                         case CKO_SECRET_KEY:
6675                                 /*
6676                                  * secret_key_obj_t is the same as
6677                                  * biginteger_t
6678                                  */
6679                                 bigint = (biginteger_t *)OBJ_SEC(obj);
6680                                 compare_bigint = B_TRUE;
6681                                 break;
6682                         case CKO_PRIVATE_KEY:
6683                                 if (obj->key_type == CKK_DSA) {
6684                                         bigint = OBJ_PRI_DSA_VALUE(obj);
6685                                 } else if (obj->key_type == CKK_DH) {
6686                                         bigint = OBJ_PRI_DH_VALUE(obj);
6687                                 } else if (obj->key_type == CKK_X9_42_DH) {
6688                                         bigint = OBJ_PRI_DH942_VALUE(obj);
6689                                 } else {
6690                                         return (B_FALSE);
6691                                 }
6692                                 compare_bigint = B_TRUE;
6693                                 break;
6694                         case CKO_PUBLIC_KEY:
6695                                 if (obj->key_type == CKK_DSA) {
6696                                         bigint = OBJ_PUB_DSA_VALUE(obj);
6697                                 } else if (obj->key_type == CKK_DH) {
6698                                         bigint = OBJ_PUB_DH_VALUE(obj);
6699                                 } else if (obj->key_type == CKK_X9_42_DH) {
6700                                         bigint = OBJ_PUB_DH942_VALUE(obj);
6701                                 } else {
6702                                         return (B_FALSE);
6703                                 }
6704                                 compare_bigint = B_TRUE;
6705                                 break;
6706                         case CKO_CERTIFICATE:
6707                                 if (obj->cert_type == CKC_X_509) {
6708                                         cert_attr = X509_CERT_VALUE(obj);
6709                                 } else if (obj->cert_type ==
6710                                     CKC_X_509_ATTR_CERT) {
6711                                         cert_attr = X509_ATTR_CERT_VALUE(obj);
6712                                 }
6713                                 compare_cert_val = B_TRUE;
6714                                 break;
6715                         default:
6716                                 return (B_FALSE);
6717                         }
6718                         break;
6719                 case CKA_MODULUS:
6720                         /* only RSA public and private key have this attr */
6721                         if (obj->key_type == CKK_RSA) {
6722                                 if (obj->class == CKO_PUBLIC_KEY) {
6723                                         bigint = OBJ_PUB_RSA_MOD(obj);
6724                                 } else if (obj->class == CKO_PRIVATE_KEY) {
6725                                         bigint = OBJ_PRI_RSA_MOD(obj);
6726                                 } else {
6727                                         return (B_FALSE);
6728                                 }
6729                                 compare_bigint = B_TRUE;
6730                         } else {
6731                                 return (B_FALSE);
6732                         }
6733                         break;
6734                 case CKA_MODULUS_BITS:
6735                         /* only RSA public key has this attribute */
6736                         if ((obj->key_type == CKK_RSA) &&
6737                             (obj->class == CKO_PUBLIC_KEY)) {
6738                                 CK_ULONG mod_bits = OBJ_PUB_RSA_MOD_BITS(obj);
6739                                 if (mod_bits !=
6740                                     *((CK_ULONG *)tmpl_attr->pValue)) {
6741                                         return (B_FALSE);
6742                                 }
6743                         } else {
6744                                 return (B_FALSE);
6745                         }
6746                         break;
6747                 case CKA_PUBLIC_EXPONENT:
6748                         /* only RSA public and private key have this attr */
6749                         if (obj->key_type == CKK_RSA) {
6750                                 if (obj->class == CKO_PUBLIC_KEY) {
6751                                         bigint = OBJ_PUB_RSA_PUBEXPO(obj);
6752                                 } else if (obj->class == CKO_PRIVATE_KEY) {
6753                                         bigint = OBJ_PRI_RSA_PUBEXPO(obj);
6754                                 } else {
6755                                         return (B_FALSE);
6756                                 }
6757                                 compare_bigint = B_TRUE;
6758                         } else {
6759                                 return (B_FALSE);
6760                         }
6761                         break;
6762                 case CKA_PRIVATE_EXPONENT:
6763                         /* only RSA private key has this attribute */
6764                         if ((obj->key_type == CKK_RSA) &&
6765                             (obj->class == CKO_PRIVATE_KEY)) {
6766                                 bigint = OBJ_PRI_RSA_PRIEXPO(obj);
6767                                 compare_bigint = B_TRUE;
6768                         } else {
6769                                 return (B_FALSE);
6770                         }
6771                         break;
6772                 case CKA_PRIME_1:
6773                         /* only RSA private key has this attribute */
6774                         if ((obj->key_type == CKK_RSA) &&
6775                             (obj->class == CKO_PRIVATE_KEY)) {
6776                                 bigint = OBJ_PRI_RSA_PRIME1(obj);
6777                                 compare_bigint = B_TRUE;
6778                         } else {
6779                                 return (B_FALSE);
6780                         }
6781                         break;
6782                 case CKA_PRIME_2:
6783                         /* only RSA private key has this attribute */
6784                         if ((obj->key_type == CKK_RSA) &&
6785                             (obj->class == CKO_PRIVATE_KEY)) {
6786                                 bigint = OBJ_PRI_RSA_PRIME2(obj);
6787                                 compare_bigint = B_TRUE;
6788                         } else {
6789                                 return (B_FALSE);
6790                         }
6791                         break;
6792                 case CKA_EXPONENT_1:
6793                         /* only RSA private key has this attribute */
6794                         if ((obj->key_type == CKK_RSA) &&
6795                             (obj->class == CKO_PRIVATE_KEY)) {
6796                                 bigint = OBJ_PRI_RSA_EXPO1(obj);
6797                                 compare_bigint = B_TRUE;
6798                         } else {
6799                                 return (B_FALSE);
6800                         }
6801                         break;
6802                 case CKA_EXPONENT_2:
6803                         /* only RSA private key has this attribute */
6804                         if ((obj->key_type == CKK_RSA) &&
6805                             (obj->class == CKO_PRIVATE_KEY)) {
6806                                 bigint = OBJ_PRI_RSA_EXPO2(obj);
6807                                 compare_bigint = B_TRUE;
6808                         } else {
6809                                 return (B_FALSE);
6810                         }
6811                         break;
6812                 case CKA_COEFFICIENT:
6813                         /* only RSA private key has this attribute */
6814                         if ((obj->key_type == CKK_RSA) &&
6815                             (obj->class == CKO_PRIVATE_KEY)) {
6816                                 bigint = OBJ_PRI_RSA_COEF(obj);
6817                                 compare_bigint = B_TRUE;
6818                         } else {
6819                                 return (B_FALSE);
6820                         }
6821                         break;
6822                 case CKA_VALUE_BITS:
6823                         /* only Diffie-Hellman private key has this attr */
6824                         if ((obj->key_type == CKK_DH) &&
6825                             (obj->class == CKO_PRIVATE_KEY)) {
6826                                 CK_ULONG val_bits = OBJ_PRI_DH_VAL_BITS(obj);
6827                                 if (val_bits !=
6828                                     *((CK_ULONG *)tmpl_attr->pValue)) {
6829                                         return (B_FALSE);
6830                                 }
6831                         } else {
6832                                 return (B_FALSE);
6833                         }
6834                         break;
6835                 case CKA_PRIME:
6836                         if (obj->class == CKO_PUBLIC_KEY) {
6837                                 switch (obj->key_type) {
6838                                 case CKK_DSA:
6839                                         bigint = OBJ_PUB_DSA_PRIME(obj);
6840                                         break;
6841                                 case CKK_DH:
6842                                         bigint = OBJ_PUB_DH_PRIME(obj);
6843                                         break;
6844                                 case CKK_X9_42_DH:
6845                                         bigint = OBJ_PUB_DH942_PRIME(obj);
6846                                         break;
6847                                 default:
6848                                         return (B_FALSE);
6849                                 }
6850                         } else if (obj->class == CKO_PRIVATE_KEY) {
6851                                 switch (obj->key_type) {
6852                                 case CKK_DSA:
6853                                         bigint = OBJ_PRI_DSA_PRIME(obj);
6854                                         break;
6855                                 case CKK_DH:
6856                                         bigint = OBJ_PRI_DH_PRIME(obj);
6857                                         break;
6858                                 case CKK_X9_42_DH:
6859                                         bigint = OBJ_PRI_DH942_PRIME(obj);
6860                                         break;
6861                                 default:
6862                                         return (B_FALSE);
6863                                 }
6864                         } else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6865                                 switch (obj->key_type) {
6866                                 case CKK_DSA:
6867                                         bigint = OBJ_DOM_DSA_PRIME(obj);
6868                                         break;
6869                                 case CKK_DH:
6870                                         bigint = OBJ_DOM_DH_PRIME(obj);
6871                                         break;
6872                                 case CKK_X9_42_DH:
6873                                         bigint = OBJ_DOM_DH942_PRIME(obj);
6874                                         break;
6875                                 default:
6876                                         return (B_FALSE);
6877                                 }
6878                         } else {
6879                                 return (B_FALSE);
6880                         }
6881                         compare_bigint = B_TRUE;
6882                         break;
6883                 case CKA_SUBPRIME:
6884                         if (obj->class == CKO_PUBLIC_KEY) {
6885                                 switch (obj->key_type) {
6886                                 case CKK_DSA:
6887                                         bigint = OBJ_PUB_DSA_SUBPRIME(obj);
6888                                         break;
6889                                 case CKK_X9_42_DH:
6890                                         bigint = OBJ_PUB_DH942_SUBPRIME(obj);
6891                                         break;
6892                                 default:
6893                                         return (B_FALSE);
6894                                 }
6895                         } else if (obj->class == CKO_PRIVATE_KEY) {
6896                                 switch (obj->key_type) {
6897                                 case CKK_DSA:
6898                                         bigint = OBJ_PRI_DSA_SUBPRIME(obj);
6899                                         break;
6900                                 case CKK_X9_42_DH:
6901                                         bigint = OBJ_PRI_DH942_SUBPRIME(obj);
6902                                         break;
6903                                 default:
6904                                         return (B_FALSE);
6905                                 }
6906                         } else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6907                                 switch (obj->key_type) {
6908                                 case CKK_DSA:
6909                                         bigint = OBJ_DOM_DSA_SUBPRIME(obj);
6910                                         break;
6911                                 case CKK_X9_42_DH:
6912                                         bigint = OBJ_DOM_DH942_SUBPRIME(obj);
6913                                         break;
6914                                 default:
6915                                         return (B_FALSE);
6916                                 }
6917                         } else {
6918                                 return (B_FALSE);
6919                         }
6920                         compare_bigint = B_TRUE;
6921                         break;
6922                 case CKA_BASE:
6923                         if (obj->class == CKO_PUBLIC_KEY) {
6924                                 switch (obj->key_type) {
6925                                 case CKK_DSA:
6926                                         bigint = OBJ_PUB_DSA_BASE(obj);
6927                                         break;
6928                                 case CKK_DH:
6929                                         bigint = OBJ_PUB_DH_BASE(obj);
6930                                         break;
6931                                 case CKK_X9_42_DH:
6932                                         bigint = OBJ_PUB_DH942_BASE(obj);
6933                                         break;
6934                                 default:
6935                                         return (B_FALSE);
6936                                 }
6937                         } else if (obj->class == CKO_PRIVATE_KEY) {
6938                                 switch (obj->key_type) {
6939                                 case CKK_DSA:
6940                                         bigint = OBJ_PRI_DSA_BASE(obj);
6941                                         break;
6942                                 case CKK_DH:
6943                                         bigint = OBJ_PRI_DH_BASE(obj);
6944                                         break;
6945                                 case CKK_X9_42_DH:
6946                                         bigint = OBJ_PRI_DH942_BASE(obj);
6947                                         break;
6948                                 default:
6949                                         return (B_FALSE);
6950                                 }
6951                         } else if (obj->class == CKO_DOMAIN_PARAMETERS) {
6952                                 switch (obj->key_type) {
6953                                 case CKK_DSA:
6954                                         bigint = OBJ_DOM_DSA_BASE(obj);
6955                                         break;
6956                                 case CKK_DH:
6957                                         bigint = OBJ_DOM_DH_BASE(obj);
6958                                         break;
6959                                 case CKK_X9_42_DH:
6960                                         bigint = OBJ_DOM_DH942_BASE(obj);
6961                                         break;
6962                                 default:
6963                                         return (B_FALSE);
6964                                 }
6965                         } else {
6966                                 return (B_FALSE);
6967                         }
6968                         compare_bigint = B_TRUE;
6969                         break;
6970                 case CKA_PRIME_BITS:
6971                         if (obj->class == CKO_DOMAIN_PARAMETERS) {
6972                                 CK_ULONG prime_bits;
6973                                 if (obj->key_type == CKK_DSA) {
6974                                         prime_bits =
6975                                             OBJ_DOM_DSA_PRIME_BITS(obj);
6976                                 } else if (obj->key_type == CKK_DH) {
6977                                         prime_bits =
6978                                             OBJ_DOM_DH_PRIME_BITS(obj);
6979                                 } else if (obj->key_type == CKK_X9_42_DH) {
6980                                         prime_bits =
6981                                             OBJ_DOM_DH942_PRIME_BITS(obj);
6982                                 } else {
6983                                         return (B_FALSE);
6984                                 }
6985                                 if (prime_bits !=
6986                                     *((CK_ULONG *)tmpl_attr->pValue)) {
6987                                         return (B_FALSE);
6988                                 }
6989                         } else {
6990                                 return (B_FALSE);
6991                         }
6992                         break;
6993                 case CKA_SUBPRIME_BITS:
6994                         if ((obj->class == CKO_DOMAIN_PARAMETERS) &&
6995                             (obj->key_type == CKK_X9_42_DH)) {
6996                                 CK_ULONG subprime_bits =
6997                                     OBJ_DOM_DH942_SUBPRIME_BITS(obj);
6998                                 if (subprime_bits !=
6999                                     *((CK_ULONG *)tmpl_attr->pValue)) {
7000                                         return (B_FALSE);
7001                                 }
7002                         } else {
7003                                 return (B_FALSE);
7004                         }
7005                         break;
7006                 default:
7007                         /*
7008                          * any other attributes are currently not supported.
7009                          * so, it's not possible for them to be in the
7010                          * object
7011                          */
7012                         return (B_FALSE);
7013                 }
7014                 if (compare_boolean) {
7015                         CK_BBOOL bval;
7016 
7017                         if (attr_mask) {
7018                                 bval = TRUE;
7019                         } else {
7020                                 bval = FALSE;
7021                         }
7022                         if (bval != *((CK_BBOOL *)tmpl_attr->pValue)) {
7023                                 return (B_FALSE);
7024                         }
7025                 } else if (compare_bigint) {
7026                         if (bigint == NULL) {
7027                                 return (B_FALSE);
7028                         }
7029                         if (tmpl_attr->ulValueLen != bigint->big_value_len) {
7030                                 return (B_FALSE);
7031                         }
7032                         if (memcmp(tmpl_attr->pValue, bigint->big_value,
7033                             tmpl_attr->ulValueLen) != 0) {
7034                                 return (B_FALSE);
7035                         }
7036                 } else if (compare_attr) {
7037                         if (obj_attr == NULL) {
7038                                 /*
7039                                  * The attribute type is valid, and its value
7040                                  * has not been initialized in the object. In
7041                                  * this case, it only matches the template's
7042                                  * attribute if the template's value length
7043                                  * is 0.
7044                                  */
7045                                 if (tmpl_attr->ulValueLen != 0)
7046                                         return (B_FALSE);
7047                         } else {
7048                                 if (tmpl_attr->ulValueLen !=
7049                                     obj_attr->ulValueLen) {
7050                                         return (B_FALSE);
7051                                 }
7052                                 if (memcmp(tmpl_attr->pValue, obj_attr->pValue,
7053                                     tmpl_attr->ulValueLen) != 0) {
7054                                         return (B_FALSE);
7055                                 }
7056                         }
7057                 } else if (compare_cert_val) {
7058                         if (cert_attr == NULL) {
7059                                 /* specific attribute not found */
7060                                 return (B_FALSE);
7061                         }
7062                         if (tmpl_attr->ulValueLen != cert_attr->length) {
7063                                 return (B_FALSE);
7064                         }
7065                         if (memcmp(tmpl_attr->pValue, cert_attr->value,
7066                             tmpl_attr->ulValueLen) != 0) {
7067                                 return (B_FALSE);
7068                         }
7069                 } else if (compare_cert_type) {
7070                         if (memcmp(tmpl_attr->pValue, &(obj->cert_type),
7071                             tmpl_attr->ulValueLen) != 0) {
7072                                 return (B_FALSE);
7073                         }
7074                 }
7075         }
7076         return (B_TRUE);
7077 }
7078 
7079 CK_ATTRIBUTE_PTR
7080 get_extra_attr(CK_ATTRIBUTE_TYPE type, soft_object_t *obj)
7081 {
7082         CK_ATTRIBUTE_INFO_PTR tmp;
7083 
7084         tmp = obj->extra_attrlistp;
7085         while (tmp != NULL) {
7086                 if (tmp->attr.type == type) {
7087                         return (&(tmp->attr));
7088                 }
7089                 tmp = tmp->next;
7090         }
7091         /* if get there, the specified attribute is not found */
7092         return (NULL);
7093 }