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