1 /*
   2  * The Initial Developer of the Original Code is International
   3  * Business Machines Corporation. Portions created by IBM
   4  * Corporation are Copyright (C) 2005 International Business
   5  * Machines Corporation. All Rights Reserved.
   6  *
   7  * This program is free software; you can redistribute it and/or modify
   8  * it under the terms of the Common Public License as published by
   9  * IBM Corporation; either version 1 of the License, or (at your option)
  10  * any later version.
  11  *
  12  * This program is distributed in the hope that it will be useful,
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * Common Public License for more details.
  16  *
  17  * You should have received a copy of the Common Public License
  18  * along with this program; if not, a copy can be viewed at
  19  * http://www.opensource.org/licenses/cpl1.0.php.
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2012 Milan Jurik. All rights reserved.
  25  * Copyright (c) 2016 by Delphix. All rights reserved.
  26  */
  27 
  28 #include <pthread.h>
  29 #include <string.h>
  30 
  31 #include <sys/types.h>
  32 #include <sys/stat.h>
  33 #include <uuid/uuid.h>
  34 #include <fcntl.h>
  35 #include <errno.h>
  36 #include <pwd.h>
  37 #include <syslog.h>
  38 
  39 #include <openssl/rsa.h>
  40 
  41 #include <tss/platform.h>
  42 #include <tss/tss_defines.h>
  43 #include <tss/tss_typedef.h>
  44 #include <tss/tss_structs.h>
  45 #include <tss/tss_error.h>
  46 #include <tss/tcs_error.h>
  47 #include <tss/tspi.h>
  48 #include <trousers/trousers.h>
  49 
  50 #include "tpmtok_int.h"
  51 #include "tpmtok_defs.h"
  52 
  53 #define MAX_RSA_KEYLENGTH 512
  54 
  55 extern void stlogit(char *fmt, ...);
  56 
  57 CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *,  CK_ULONG);
  58 int tok_slot2local(CK_SLOT_ID);
  59 CK_RV token_specific_session(CK_SLOT_ID);
  60 CK_RV token_specific_final(TSS_HCONTEXT);
  61 
  62 CK_RV
  63 token_specific_rsa_decrypt(
  64         TSS_HCONTEXT,
  65         CK_BYTE *,
  66         CK_ULONG,
  67         CK_BYTE *,
  68         CK_ULONG *,
  69         OBJECT *);
  70 
  71 CK_RV
  72 token_specific_rsa_encrypt(
  73         TSS_HCONTEXT,
  74         CK_BYTE *,
  75         CK_ULONG,
  76         CK_BYTE *,
  77         CK_ULONG *,
  78         OBJECT *);
  79 
  80 CK_RV
  81 token_specific_rsa_sign(
  82         TSS_HCONTEXT,
  83         CK_BYTE *,
  84         CK_ULONG,
  85         CK_BYTE *,
  86         CK_ULONG *,
  87         OBJECT *);
  88 
  89 CK_RV
  90 token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *,
  91     CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *);
  92 
  93 CK_RV
  94 token_specific_rsa_generate_keypair(TSS_HCONTEXT,
  95         TEMPLATE *,
  96         TEMPLATE *);
  97 
  98 CK_RV
  99 token_specific_sha_init(DIGEST_CONTEXT *);
 100 
 101 CK_RV
 102 token_specific_sha_update(DIGEST_CONTEXT *,
 103         CK_BYTE *,
 104         CK_ULONG);
 105 
 106 CK_RV
 107 token_specific_sha_final(DIGEST_CONTEXT *,
 108         CK_BYTE *,
 109         CK_ULONG *);
 110 
 111 CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG);
 112 CK_RV token_specific_logout(TSS_HCONTEXT);
 113 CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
 114 CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR,
 115         CK_ULONG, CK_CHAR_PTR, CK_ULONG);
 116 CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG);
 117 
 118 static CK_RV
 119 token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *);
 120 
 121 struct token_specific_struct token_specific = {
 122         "TPM_Debug",
 123         &token_specific_init,
 124         NULL,
 125         &token_rng,
 126         &token_specific_session,
 127         &token_specific_final,
 128         &token_specific_rsa_decrypt,
 129         &token_specific_rsa_encrypt,
 130         &token_specific_rsa_sign,
 131         &token_specific_rsa_verify,
 132         &token_specific_rsa_generate_keypair,
 133         NULL,
 134         NULL,
 135         NULL,
 136         &token_specific_login,
 137         &token_specific_logout,
 138         &token_specific_init_pin,
 139         &token_specific_set_pin,
 140         &token_specific_verify_so_pin
 141 };
 142 
 143 /* The context we'll use globally to connect to the TSP */
 144 
 145 /* TSP key handles */
 146 TSS_HKEY hPublicRootKey = NULL_HKEY;
 147 TSS_HKEY hPublicLeafKey = NULL_HKEY;
 148 TSS_HKEY hPrivateRootKey = NULL_HKEY;
 149 TSS_HKEY hPrivateLeafKey = NULL_HKEY;
 150 
 151 TSS_UUID publicRootKeyUUID;
 152 TSS_UUID publicLeafKeyUUID;
 153 TSS_UUID privateRootKeyUUID;
 154 TSS_UUID privateLeafKeyUUID;
 155 
 156 /* TSP policy handles */
 157 TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY;
 158 
 159 /* PKCS#11 key handles */
 160 int not_initialized = 0;
 161 
 162 CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH];
 163 CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH];
 164 
 165 static TPM_CAP_VERSION_INFO tpmvinfo;
 166 
 167 static CK_RV
 168 verify_user_pin(TSS_HCONTEXT, CK_BYTE *);
 169 
 170 static TSS_RESULT
 171 tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *);
 172 
 173 static TSS_RESULT
 174 set_legacy_key_params(TSS_HKEY);
 175 
 176 static void
 177 local_uuid_clear(TSS_UUID *uuid)
 178 {
 179         if (uuid == NULL)
 180                 return;
 181         (void) memset(uuid, 0, sizeof (TSS_UUID));
 182 }
 183 
 184 
 185 /* convert from TSS_UUID to uuid_t */
 186 static void
 187 tss_uuid_convert_from(TSS_UUID *uu, uuid_t ptr)
 188 {
 189         uint_t          tmp;
 190         uchar_t         *out = ptr;
 191 
 192         tmp = ntohl(uu->ulTimeLow);
 193         out[3] = (uchar_t)tmp;
 194         tmp >>= 8;
 195         out[2] = (uchar_t)tmp;
 196         tmp >>= 8;
 197         out[1] = (uchar_t)tmp;
 198         tmp >>= 8;
 199         out[0] = (uchar_t)tmp;
 200 
 201         tmp = ntohs(uu->usTimeMid);
 202         out[5] = (uchar_t)tmp;
 203         tmp >>= 8;
 204         out[4] = (uchar_t)tmp;
 205 
 206         tmp = ntohs(uu->usTimeHigh);
 207         out[7] = (uchar_t)tmp;
 208         tmp >>= 8;
 209         out[6] = (uchar_t)tmp;
 210 
 211         tmp = uu->bClockSeqHigh;
 212         out[8] = (uchar_t)tmp;
 213         tmp = uu->bClockSeqLow;
 214         out[9] = (uchar_t)tmp;
 215 
 216         (void) memcpy(out+10, uu->rgbNode, 6);
 217 }
 218 
 219 /* convert from uuid_t to TSS_UUID */
 220 static void
 221 tss_uuid_convert_to(TSS_UUID *uuid, uuid_t in)
 222 {
 223         uchar_t         *ptr;
 224         uint32_t        ltmp;
 225         uint16_t        stmp;
 226 
 227         ptr = in;
 228 
 229         ltmp = *ptr++;
 230         ltmp = (ltmp << 8) | *ptr++;
 231         ltmp = (ltmp << 8) | *ptr++;
 232         ltmp = (ltmp << 8) | *ptr++;
 233         uuid->ulTimeLow = ntohl(ltmp);
 234 
 235         stmp = *ptr++;
 236         stmp = (stmp << 8) | *ptr++;
 237         uuid->usTimeMid = ntohs(stmp);
 238 
 239         stmp = *ptr++;
 240         stmp = (stmp << 8) | *ptr++;
 241         uuid->usTimeHigh = ntohs(stmp);
 242 
 243         uuid->bClockSeqHigh = *ptr++;
 244 
 245         uuid->bClockSeqLow = *ptr++;
 246 
 247         (void) memcpy(uuid->rgbNode, ptr, 6);
 248 }
 249 
 250 static void
 251 local_uuid_copy(TSS_UUID *dst, TSS_UUID *src)
 252 {
 253         uuid_t udst, usrc;
 254 
 255         tss_uuid_convert_from(dst, udst);
 256         tss_uuid_convert_from(src, usrc);
 257 
 258         uuid_copy(udst, usrc);
 259 
 260         tss_uuid_convert_to(dst, udst);
 261 }
 262 
 263 static void
 264 local_uuid_generate(TSS_UUID *uu)
 265 {
 266         uuid_t newuuid;
 267 
 268         uuid_generate(newuuid);
 269 
 270         tss_uuid_convert_to(uu, newuuid);
 271 }
 272 
 273 static int
 274 local_copy_file(char *dst, char *src)
 275 {
 276         FILE *fdest, *fsrc;
 277         char line[BUFSIZ];
 278 
 279         fdest = fopen(dst, "w");
 280         if (fdest == NULL)
 281                 return (-1);
 282 
 283         fsrc = fopen(src, "r");
 284         if (fsrc == NULL) {
 285                 (void) fclose(fdest);
 286                 return (-1);
 287         }
 288 
 289         while (fread(line, sizeof (line), 1, fsrc))
 290                 (void) fprintf(fdest, "%s\n", line);
 291         (void) fclose(fsrc);
 292         (void) fclose(fdest);
 293         return (0);
 294 }
 295 
 296 static int
 297 remove_uuid(char *keyname)
 298 {
 299         int ret = 0;
 300         FILE *fp, *newfp;
 301         char fname[MAXPATHLEN];
 302         char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
 303         char *tmpfname;
 304         char *p = get_tpm_keystore_path();
 305 
 306         if (p == NULL)
 307                 return (-1);
 308 
 309         (void) snprintf(fname, sizeof (fname),
 310             "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
 311 
 312         fp = fopen(fname, "r");
 313         if (fp == NULL) {
 314                 return (-1);
 315         }
 316 
 317         tmpfname = tempnam("/tmp", "tpmtok");
 318         newfp = fopen(tmpfname, "w+");
 319         if (newfp == NULL) {
 320                 free(tmpfname);
 321                 (void) fclose(fp);
 322                 return (-1);
 323         }
 324 
 325         while (!feof(fp)) {
 326                 (void) fgets(line, sizeof (line), fp);
 327                 if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
 328                         if (strcmp(key, keyname))
 329                                 (void) fprintf(newfp, "%s\n", line);
 330                 }
 331         }
 332 
 333         (void) fclose(fp);
 334         (void) fclose(newfp);
 335         if (local_copy_file(fname, tmpfname) == 0)
 336                 (void) unlink(tmpfname);
 337 
 338         free(tmpfname);
 339 
 340         return (ret);
 341 }
 342 
 343 static int
 344 find_uuid(char *keyname, TSS_UUID *uu)
 345 {
 346         int ret = 0, found = 0;
 347         FILE *fp = NULL;
 348         char fname[MAXPATHLEN];
 349         char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ];
 350         uuid_t uuid;
 351         char *p = get_tpm_keystore_path();
 352 
 353         if (p == NULL)
 354                 return (-1);
 355 
 356         tss_uuid_convert_from(uu, uuid);
 357 
 358         (void) snprintf(fname, sizeof (fname),
 359             "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
 360 
 361         /* Open UUID Index file */
 362         fp = fopen(fname, "r");
 363         if (fp == NULL) {
 364                 if (errno == ENOENT) {
 365                         /* initialize the file */
 366                         fp = fopen(fname, "w");
 367                         if (fp != NULL)
 368                                 (void) fclose(fp);
 369                 }
 370                 return (-1);
 371         }
 372 
 373         while (!feof(fp)) {
 374                 (void) fgets(line, sizeof (line), fp);
 375                 if (sscanf(line, "%1024s %1024s", key, idstr) == 2) {
 376                         if (strcmp(key, keyname) == 0) {
 377                                 ret = uuid_parse(idstr, uuid);
 378                                 if (ret == 0) {
 379                                         found = 1;
 380                                         tss_uuid_convert_to(uu,
 381                                             uuid);
 382                                 }
 383                                 break;
 384                         }
 385                 }
 386         }
 387         (void) fclose(fp);
 388 
 389         if (!found)
 390                 ret = -1;
 391         return (ret);
 392 }
 393 
 394 static int
 395 local_uuid_is_null(TSS_UUID *uu)
 396 {
 397         uuid_t uuid;
 398         int nulluuid;
 399 
 400         tss_uuid_convert_from(uu, uuid);
 401 
 402         nulluuid = uuid_is_null(uuid);
 403         return (nulluuid);
 404 }
 405 
 406 static int
 407 add_uuid(char *keyname, TSS_UUID *uu)
 408 {
 409         FILE *fp = NULL;
 410         char fname[MAXPATHLEN];
 411         char idstr[BUFSIZ];
 412         uuid_t uuid;
 413         char *p = get_tpm_keystore_path();
 414 
 415         if (p == NULL)
 416                 return (-1);
 417 
 418         tss_uuid_convert_from(uu, uuid);
 419 
 420         if (uuid_is_null(uuid))
 421                 return (-1);
 422 
 423         uuid_unparse(uuid, idstr);
 424 
 425         (void) snprintf(fname, sizeof (fname),
 426             "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME);
 427 
 428         fp = fopen(fname, "a");
 429         if (fp == NULL)
 430                 return (-1);
 431 
 432         (void) fprintf(fp, "%s %s\n", keyname, idstr);
 433         (void) fclose(fp);
 434 
 435         return (0);
 436 }
 437 
 438 
 439 static UINT32
 440 util_get_keysize_flag(CK_ULONG size)
 441 {
 442         switch (size) {
 443                 case 512:
 444                         return (TSS_KEY_SIZE_512);
 445                 case 1024:
 446                         return (TSS_KEY_SIZE_1024);
 447                 case 2048:
 448                         return (TSS_KEY_SIZE_2048);
 449                 default:
 450                         break;
 451         }
 452 
 453         return (0);
 454 }
 455 
 456 /* make sure the public exponent attribute is 65537 */
 457 static CK_ULONG
 458 util_check_public_exponent(TEMPLATE *tmpl)
 459 {
 460         CK_BBOOL flag;
 461         CK_ATTRIBUTE *publ_exp_attr;
 462         CK_BYTE pubexp_bytes[] = { 1, 0, 1 };
 463         CK_ULONG publ_exp, rc = 1;
 464 
 465         flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT,
 466             &publ_exp_attr);
 467         if (!flag) {
 468                 LogError1("Couldn't find public exponent attribute");
 469                 return (CKR_TEMPLATE_INCOMPLETE);
 470         }
 471 
 472         switch (publ_exp_attr->ulValueLen) {
 473                 case 3:
 474                         rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3);
 475                         break;
 476                 case sizeof (CK_ULONG):
 477                         publ_exp = *((CK_ULONG *)publ_exp_attr->pValue);
 478                         if (publ_exp == 65537)
 479                                 rc = 0;
 480                         break;
 481                 default:
 482                         break;
 483         }
 484 
 485         return (rc);
 486 }
 487 
 488 TSS_RESULT
 489 set_public_modulus(TSS_HCONTEXT hContext, TSS_HKEY hKey,
 490         unsigned long size_n, unsigned char *n)
 491 {
 492         UINT64 offset;
 493         UINT32 blob_size;
 494         BYTE *blob, pub_blob[1024];
 495         TCPA_PUBKEY pub_key;
 496         TSS_RESULT result;
 497 
 498         /* Get the TCPA_PUBKEY blob from the key object. */
 499         result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
 500             TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob);
 501         if (result != TSS_SUCCESS) {
 502                 stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n",
 503                     result, Trspi_Error_String(result));
 504                 return (result);
 505         }
 506 
 507         offset = 0;
 508         result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key);
 509         if (result != TSS_SUCCESS) {
 510                 stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n",
 511                     result, Trspi_Error_String(result));
 512                 return (result);
 513         }
 514 
 515         Tspi_Context_FreeMemory(hContext, blob);
 516         /* Free the first dangling reference, putting 'n' in its place */
 517         free(pub_key.pubKey.key);
 518         pub_key.pubKey.keyLength = size_n;
 519         pub_key.pubKey.key = n;
 520 
 521         offset = 0;
 522         Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key);
 523 
 524         /* Free the second dangling reference */
 525         free(pub_key.algorithmParms.parms);
 526 
 527         /* set the public key data in the TSS object */
 528         result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
 529             TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob);
 530         if (result != TSS_SUCCESS) {
 531                 stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n",
 532                     result, Trspi_Error_String(result));
 533                 return (result);
 534         }
 535 
 536         return (result);
 537 }
 538 
 539 /*
 540  * Get details about the TPM to put into the token_info structure.
 541  */
 542 CK_RV
 543 token_get_tpm_info(TSS_HCONTEXT hContext, TOKEN_DATA *td)
 544 {
 545         TSS_RESULT result;
 546         TPM_CAPABILITY_AREA capArea = TSS_TPMCAP_VERSION_VAL;
 547         UINT32 datalen;
 548         BYTE *data;
 549         TSS_HTPM hTPM;
 550 
 551         if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
 552                 stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
 553                     result, Trspi_Error_String(result));
 554                 return (CKR_FUNCTION_FAILED);
 555         }
 556         if ((result = Tspi_TPM_GetCapability(hTPM,
 557             capArea, 0, NULL, &datalen, &data)) != 0 || datalen == 0 ||
 558             data == NULL) {
 559                 stlogit("Tspi_Context_GetCapability: 0x%0x - %s",
 560                     result, Trspi_Error_String(result));
 561                 return (CKR_FUNCTION_FAILED);
 562         }
 563         if (datalen > sizeof (tpmvinfo)) {
 564                 Tspi_Context_FreeMemory(hContext, data);
 565                 return (CKR_FUNCTION_FAILED);
 566         }
 567 
 568         (void) memcpy(&tpmvinfo, (void *)data, datalen);
 569 
 570         bzero(td->token_info.manufacturerID,
 571             sizeof (td->token_info.manufacturerID));
 572 
 573         (void) memset(td->token_info.manufacturerID,  ' ',
 574             sizeof (td->token_info.manufacturerID) - 1);
 575 
 576         (void) memcpy(td->token_info.manufacturerID,
 577             tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID));
 578 
 579         (void) memset(td->token_info.label, ' ',
 580             sizeof (td->token_info.label) - 1);
 581 
 582         (void) memcpy(td->token_info.label, "TPM", 3);
 583 
 584         td->token_info.hardwareVersion.major = tpmvinfo.version.major;
 585         td->token_info.hardwareVersion.minor = tpmvinfo.version.minor;
 586         td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor;
 587         td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor;
 588 
 589         Tspi_Context_FreeMemory(hContext, data);
 590         return (CKR_OK);
 591 }
 592 
 593 /*ARGSUSED*/
 594 CK_RV
 595 token_specific_session(CK_SLOT_ID  slotid)
 596 {
 597         return (CKR_OK);
 598 }
 599 
 600 CK_RV
 601 token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes)
 602 {
 603         TSS_RESULT rc;
 604         TSS_HTPM hTPM;
 605         BYTE *random_bytes = NULL;
 606 
 607         if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
 608                 stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
 609                     rc, Trspi_Error_String(rc));
 610                 return (CKR_FUNCTION_FAILED);
 611         }
 612 
 613         if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) {
 614                 stlogit("Tspi_TPM_GetRandom: 0x%0x - %s",
 615                     rc, Trspi_Error_String(rc));
 616                 return (CKR_FUNCTION_FAILED);
 617         }
 618 
 619         (void) memcpy(output, random_bytes, bytes);
 620         Tspi_Context_FreeMemory(hContext, random_bytes);
 621 
 622         return (CKR_OK);
 623 }
 624 
 625 TSS_RESULT
 626 open_tss_context(TSS_HCONTEXT *pContext)
 627 {
 628         TSS_RESULT result;
 629 
 630         if ((result = Tspi_Context_Create(pContext))) {
 631                 stlogit("Tspi_Context_Create: 0x%0x - %s",
 632                     result, Trspi_Error_String(result));
 633                 return (CKR_FUNCTION_FAILED);
 634         }
 635 
 636         if ((result = Tspi_Context_Connect(*pContext, NULL))) {
 637                 stlogit("Tspi_Context_Connect: 0x%0x - %s",
 638                     result, Trspi_Error_String(result));
 639                 Tspi_Context_Close(*pContext);
 640                 *pContext = 0;
 641                 return (CKR_FUNCTION_FAILED);
 642         }
 643         return (result);
 644 }
 645 
 646 /*ARGSUSED*/
 647 static CK_RV
 648 token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber,
 649     TSS_HCONTEXT *hContext)
 650 {
 651         TSS_RESULT result;
 652 
 653         result = open_tss_context(hContext);
 654         if (result)
 655                 return (CKR_FUNCTION_FAILED);
 656 
 657         if ((result = Tspi_Context_GetDefaultPolicy(*hContext,
 658             &hDefaultPolicy))) {
 659                 stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s",
 660                     result, Trspi_Error_String(result));
 661                 return (CKR_FUNCTION_FAILED);
 662         }
 663 
 664         local_uuid_clear(&publicRootKeyUUID);
 665         local_uuid_clear(&privateRootKeyUUID);
 666         local_uuid_clear(&publicLeafKeyUUID);
 667         local_uuid_clear(&privateLeafKeyUUID);
 668 
 669         result = token_get_tpm_info(*hContext, nv_token_data);
 670         return (result);
 671 }
 672 
 673 /*
 674  * Given a modulus and prime from an RSA key, create a TSS_HKEY object by
 675  * wrapping the RSA key with a key from the TPM (SRK or other previously stored
 676  * key).
 677  */
 678 static CK_RV
 679 token_wrap_sw_key(
 680         TSS_HCONTEXT hContext,
 681         int size_n,
 682         unsigned char *n,
 683         int size_p,
 684         unsigned char *p,
 685         TSS_HKEY hParentKey,
 686         TSS_FLAG initFlags,
 687         TSS_HKEY *phKey)
 688 {
 689         TSS_RESULT result;
 690         UINT32 key_size;
 691 
 692         key_size = util_get_keysize_flag(size_n * 8);
 693         if (initFlags == 0) {
 694                 return (CKR_FUNCTION_FAILED);
 695         }
 696 
 697         /* create the TSS key object */
 698         result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
 699             TSS_KEY_MIGRATABLE | initFlags | key_size, phKey);
 700         if (result != TSS_SUCCESS) {
 701                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
 702                     result, Trspi_Error_String(result));
 703                 return (CKR_FUNCTION_FAILED);
 704         }
 705 
 706         result = set_public_modulus(hContext, *phKey, size_n, n);
 707         if (result != TSS_SUCCESS) {
 708                 Tspi_Context_CloseObject(hContext, *phKey);
 709                 *phKey = NULL_HKEY;
 710                 return (CKR_FUNCTION_FAILED);
 711         }
 712 
 713         /* set the private key data in the TSS object */
 714         result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
 715             TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p);
 716         if (result != TSS_SUCCESS) {
 717                 stlogit("Tspi_SetAttribData: 0x%x - %s",
 718                     result, Trspi_Error_String(result));
 719                 Tspi_Context_CloseObject(hContext, *phKey);
 720                 *phKey = NULL_HKEY;
 721                 return (CKR_FUNCTION_FAILED);
 722         }
 723 
 724         result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION,
 725             *phKey, NULL);
 726 
 727         if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
 728                 if ((result = Tspi_SetAttribUint32(*phKey,
 729                     TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
 730                     TSS_ES_RSAESPKCSV15))) {
 731                         stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
 732                             result, Trspi_Error_String(result));
 733                         Tspi_Context_CloseObject(hContext, *phKey);
 734                         return (CKR_FUNCTION_FAILED);
 735                 }
 736 
 737                 if ((result = Tspi_SetAttribUint32(*phKey,
 738                     TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
 739                     TSS_SS_RSASSAPKCS1V15_DER))) {
 740                         stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n",
 741                             result, Trspi_Error_String(result));
 742                         Tspi_Context_CloseObject(hContext, *phKey);
 743                         return (CKR_FUNCTION_FAILED);
 744                 }
 745         }
 746 
 747         result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS);
 748         if (result != TSS_SUCCESS) {
 749                 stlogit("Tspi_Key_WrapKey: 0x%0x - %s",
 750                     result, Trspi_Error_String(result));
 751                 Tspi_Context_CloseObject(hContext, *phKey);
 752                 *phKey = NULL_HKEY;
 753                 return (CKR_FUNCTION_FAILED);
 754         }
 755 
 756         return (CKR_OK);
 757 }
 758 
 759 /*
 760  * Create a TPM key blob for an imported key. This function is only called when
 761  * a key is in active use, so any failure should trickle through.
 762  */
 763 static CK_RV
 764 token_wrap_key_object(TSS_HCONTEXT hContext,
 765         CK_OBJECT_HANDLE ckObject,
 766         TSS_HKEY hParentKey, TSS_HKEY *phKey)
 767 {
 768         CK_RV           rc = CKR_OK;
 769         CK_ATTRIBUTE    *attr = NULL, *new_attr, *prime_attr;
 770         CK_ULONG        class, key_type;
 771         OBJECT          *obj;
 772 
 773         TSS_RESULT      result;
 774         TSS_FLAG        initFlags = 0;
 775         BYTE            *rgbBlob;
 776         UINT32          ulBlobLen;
 777 
 778         if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) {
 779                 return (rc);
 780         }
 781 
 782         /* if the object isn't a key, fail */
 783         if (template_attribute_find(obj->template, CKA_KEY_TYPE,
 784             &attr) == FALSE) {
 785                 return (CKR_TEMPLATE_INCOMPLETE);
 786         }
 787 
 788         key_type = *((CK_ULONG *)attr->pValue);
 789 
 790         if (key_type != CKK_RSA) {
 791                 return (CKR_TEMPLATE_INCONSISTENT);
 792         }
 793 
 794         if (template_attribute_find(obj->template, CKA_CLASS,
 795             &attr) == FALSE) {
 796                 return (CKR_TEMPLATE_INCOMPLETE);
 797         }
 798 
 799         class = *((CK_ULONG *)attr->pValue);
 800 
 801         if (class == CKO_PRIVATE_KEY) {
 802                 /*
 803                  * In order to create a full TSS key blob using a PKCS#11
 804                  * private key object, we need one of the two primes, the
 805                  * modulus and the private exponent and we need the public
 806                  * exponent to be correct.
 807                  */
 808 
 809                 /*
 810                  * Check the least likely attribute to exist first, the
 811                  * primes.
 812                  */
 813                 if (template_attribute_find(obj->template, CKA_PRIME_1,
 814                     &prime_attr) == FALSE) {
 815                         if (template_attribute_find(obj->template,
 816                             CKA_PRIME_2, &prime_attr) == FALSE) {
 817                                 return (CKR_TEMPLATE_INCOMPLETE);
 818                         }
 819                 }
 820 
 821                 /* Make sure the public exponent is usable */
 822                 if ((rc = util_check_public_exponent(obj->template))) {
 823                         return (CKR_TEMPLATE_INCONSISTENT);
 824                 }
 825 
 826                 /* get the modulus */
 827                 if (template_attribute_find(obj->template, CKA_MODULUS,
 828                     &attr) == FALSE) {
 829                         return (CKR_TEMPLATE_INCOMPLETE);
 830                 }
 831 
 832                 /* make sure the key size is usable */
 833                 initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
 834                 if (initFlags == 0) {
 835                         return (CKR_TEMPLATE_INCONSISTENT);
 836                 }
 837 
 838                 /* generate the software based key */
 839                 if ((rc = token_wrap_sw_key(hContext,
 840                     (int)attr->ulValueLen, attr->pValue,
 841                     (int)prime_attr->ulValueLen, prime_attr->pValue,
 842                     hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION,
 843                     phKey))) {
 844                         return (rc);
 845                 }
 846         } else if (class == CKO_PUBLIC_KEY) {
 847                 /* Make sure the public exponent is usable */
 848                 if ((util_check_public_exponent(obj->template))) {
 849                         return (CKR_TEMPLATE_INCONSISTENT);
 850                 }
 851 
 852                 /* grab the modulus to put into the TSS key object */
 853                 if (template_attribute_find(obj->template,
 854                     CKA_MODULUS, &attr) == FALSE) {
 855                         return (CKR_TEMPLATE_INCONSISTENT);
 856                 }
 857 
 858                 /* make sure the key size is usable */
 859                 initFlags = util_get_keysize_flag(attr->ulValueLen * 8);
 860                 if (initFlags == 0) {
 861                         return (CKR_TEMPLATE_INCONSISTENT);
 862                 }
 863 
 864                 initFlags |= TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION |
 865                     TSS_KEY_TYPE_LEGACY;
 866 
 867                 if ((result = Tspi_Context_CreateObject(hContext,
 868                     TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
 869                         stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
 870                             result, Trspi_Error_String(result));
 871                         return (result);
 872                 }
 873 
 874                 if ((result = set_public_modulus(hContext, *phKey,
 875                     attr->ulValueLen, attr->pValue))) {
 876                         Tspi_Context_CloseObject(hContext, *phKey);
 877                         *phKey = NULL_HKEY;
 878                         return (CKR_FUNCTION_FAILED);
 879                 }
 880                 result = tss_assign_secret_key_policy(hContext,
 881                     TSS_POLICY_MIGRATION, *phKey, NULL);
 882                 if (result) {
 883                         Tspi_Context_CloseObject(hContext, *phKey);
 884                         *phKey = NULL_HKEY;
 885                         return (CKR_FUNCTION_FAILED);
 886                 }
 887 
 888                 result = set_legacy_key_params(*phKey);
 889                 if (result) {
 890                         Tspi_Context_CloseObject(hContext, *phKey);
 891                         *phKey = NULL_HKEY;
 892                         return (CKR_FUNCTION_FAILED);
 893                 }
 894         } else {
 895                 return (CKR_FUNCTION_FAILED);
 896         }
 897 
 898         /* grab the entire key blob to put into the PKCS#11 object */
 899         if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB,
 900             TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
 901                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
 902                     result, Trspi_Error_String(result));
 903                 return (CKR_FUNCTION_FAILED);
 904         }
 905 
 906         /* insert the key blob into the object */
 907         if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen,
 908             &new_attr))) {
 909                 Tspi_Context_FreeMemory(hContext, rgbBlob);
 910                 return (rc);
 911         }
 912         (void) template_update_attribute(obj->template, new_attr);
 913         Tspi_Context_FreeMemory(hContext, rgbBlob);
 914 
 915         /*
 916          * If this is a token object, save it with the new attribute
 917          * so that we don't have to go down this path again.
 918          */
 919         if (!object_is_session_object(obj)) {
 920                 rc = save_token_object(hContext, obj);
 921         }
 922 
 923         return (rc);
 924 }
 925 
 926 static TSS_RESULT
 927 tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_FLAG policyType,
 928     TSS_HKEY hKey, CK_CHAR *passHash)
 929 {
 930         TSS_RESULT result;
 931         TSS_HPOLICY hPolicy;
 932 
 933         if ((result = Tspi_Context_CreateObject(hContext,
 934             TSS_OBJECT_TYPE_POLICY, policyType, &hPolicy))) {
 935                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
 936                     result, Trspi_Error_String(result));
 937                 return (result);
 938         }
 939         if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) {
 940                 stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
 941                     result, Trspi_Error_String(result));
 942                 goto done;
 943         }
 944         if (passHash == NULL) {
 945                 result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE,
 946                     0, NULL);
 947         } else {
 948                 result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
 949                     SHA1_DIGEST_LENGTH, passHash);
 950         }
 951         if (result != TSS_SUCCESS) {
 952                 stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
 953                     result, Trspi_Error_String(result));
 954                 goto done;
 955         }
 956 done:
 957         if (result != TSS_SUCCESS)
 958                 Tspi_Context_CloseObject(hContext, hPolicy);
 959         return (result);
 960 }
 961 
 962 /*
 963  * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped
 964  * by an already TPM-resident key and protected with a PIN (optional).
 965  */
 966 static CK_RV
 967 token_load_key(
 968         TSS_HCONTEXT hContext,
 969         CK_OBJECT_HANDLE ckKey,
 970         TSS_HKEY hParentKey,
 971         CK_CHAR_PTR passHash,
 972         TSS_HKEY *phKey)
 973 {
 974         TSS_RESULT result;
 975         CK_RV rc;
 976 
 977         /*
 978          * The key blob wasn't found, load the parts of the key
 979          * from the object DB and create a new key object that
 980          * gets loaded into the TPM, wrapped with the parent key.
 981          */
 982         if ((rc = token_wrap_key_object(hContext, ckKey,
 983             hParentKey, phKey))) {
 984                 return (rc);
 985         }
 986 
 987         /*
 988          * Assign the PIN hash (optional) to the newly loaded key object,
 989          * if this PIN is incorrect, the TPM will not be able to decrypt
 990          * the private key and use it.
 991          */
 992         result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
 993             *phKey, passHash);
 994 
 995         return (result);
 996 }
 997 
 998 /*
 999  * Load the SRK into the TPM by referencing its well-known UUID and using the
1000  * default SRK PIN (20 bytes of 0x00).
1001  *
1002  * NOTE - if the SRK PIN is changed by an administrative tool, this code will
1003  * fail because it assumes that the well-known PIN is still being used.
1004  */
1005 static TSS_RESULT
1006 token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK)
1007 {
1008         TSS_HPOLICY hPolicy;
1009         TSS_RESULT result;
1010         TSS_UUID SRK_UUID = TSS_UUID_SRK;
1011         BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET;
1012         TSS_HTPM hTPM;
1013 
1014         if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) {
1015                 stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s",
1016                     result, Trspi_Error_String(result));
1017                 return (CKR_FUNCTION_FAILED);
1018         }
1019 
1020         /* load the SRK */
1021         if ((result = Tspi_Context_LoadKeyByUUID(hContext,
1022             TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) {
1023                 stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s",
1024                     result, Trspi_Error_String(result));
1025                 goto done;
1026         }
1027         if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE,
1028             &hPolicy))) {
1029                 stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
1030                     result, Trspi_Error_String(result));
1031                 goto done;
1032         }
1033         if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
1034             sizeof (wellKnown), wellKnown))) {
1035                 stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1036                     result, Trspi_Error_String(result));
1037                 goto done;
1038         }
1039 
1040 done:
1041         return (result);
1042 }
1043 
1044 static TSS_RESULT
1045 tss_find_and_load_key(TSS_HCONTEXT hContext,
1046         char *keyid, TSS_UUID *uuid, TSS_HKEY hParent,
1047         BYTE *hash, TSS_HKEY *hKey)
1048 {
1049         TSS_RESULT result;
1050 
1051         if (local_uuid_is_null(uuid) &&
1052             find_uuid(keyid, uuid)) {
1053                 /* The UUID was not created or saved yet */
1054                 return (1);
1055         }
1056         result = Tspi_Context_GetKeyByUUID(hContext,
1057             TSS_PS_TYPE_USER, *uuid, hKey);
1058         if (result) {
1059                 stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s",
1060                     result, Trspi_Error_String(result));
1061                 return (result);
1062         }
1063 
1064         if (hash != NULL) {
1065                 result = tss_assign_secret_key_policy(hContext,
1066                     TSS_POLICY_USAGE, *hKey, (CK_BYTE *)hash);
1067                 if (result)
1068                         return (result);
1069         }
1070 
1071         result = Tspi_Key_LoadKey(*hKey, hParent);
1072         if (result)
1073                 stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1074                     result, Trspi_Error_String(result));
1075 
1076         return (result);
1077 }
1078 
1079 static TSS_RESULT
1080 token_load_public_root_key(TSS_HCONTEXT hContext)
1081 {
1082         TSS_RESULT result;
1083         TSS_HKEY hSRK;
1084 
1085         if (hPublicRootKey != NULL_HKEY)
1086                 return (TSS_SUCCESS);
1087 
1088         if ((result = token_load_srk(hContext, &hSRK))) {
1089                 return (result);
1090         }
1091 
1092         result = tss_find_and_load_key(hContext,
1093             TPMTOK_PUBLIC_ROOT_KEY_ID,
1094             &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey);
1095         if (result)
1096                 return (result);
1097 
1098         return (result);
1099 }
1100 
1101 static TSS_RESULT
1102 set_legacy_key_params(TSS_HKEY hKey)
1103 {
1104         TSS_RESULT result;
1105 
1106         if ((result = Tspi_SetAttribUint32(hKey,
1107             TSS_TSPATTRIB_KEY_INFO,
1108             TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
1109             TSS_ES_RSAESPKCSV15))) {
1110                 stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1111                     result, Trspi_Error_String(result));
1112                 return (result);
1113         }
1114 
1115         if ((result = Tspi_SetAttribUint32(hKey,
1116             TSS_TSPATTRIB_KEY_INFO,
1117             TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1118             TSS_SS_RSASSAPKCS1V15_DER))) {
1119                 stlogit("Tspi_SetAttribUint32: 0x%0x - %s",
1120                     result, Trspi_Error_String(result));
1121                 return (result);
1122         }
1123 
1124         return (result);
1125 }
1126 
1127 static TSS_RESULT
1128 tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash,
1129         TSS_HKEY hParentKey, TSS_HKEY *phKey)
1130 {
1131         TSS_RESULT      result;
1132         TSS_HPOLICY     hMigPolicy;
1133 
1134         if ((result = Tspi_Context_CreateObject(hContext,
1135             TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) {
1136                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1137                     result, Trspi_Error_String(result));
1138                 return (result);
1139         }
1140         result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
1141             *phKey, passHash);
1142 
1143         if (result) {
1144                 Tspi_Context_CloseObject(hContext, *phKey);
1145                 return (result);
1146         }
1147 
1148         if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) {
1149                 if ((result = Tspi_Context_CreateObject(hContext,
1150                     TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION,
1151                     &hMigPolicy))) {
1152                         stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1153                             result, Trspi_Error_String(result));
1154                         Tspi_Context_CloseObject(hContext, *phKey);
1155                         return (result);
1156                 }
1157 
1158                 if (passHash == NULL) {
1159                         result = Tspi_Policy_SetSecret(hMigPolicy,
1160                             TSS_SECRET_MODE_NONE, 0, NULL);
1161                 } else {
1162                         result = Tspi_Policy_SetSecret(hMigPolicy,
1163                             TSS_SECRET_MODE_SHA1, 20, passHash);
1164                 }
1165 
1166                 if (result != TSS_SUCCESS) {
1167                         stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1168                             result, Trspi_Error_String(result));
1169                         Tspi_Context_CloseObject(hContext, *phKey);
1170                         Tspi_Context_CloseObject(hContext, hMigPolicy);
1171                         return (result);
1172                 }
1173 
1174                 if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) {
1175                         stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s",
1176                             result, Trspi_Error_String(result));
1177                         Tspi_Context_CloseObject(hContext, *phKey);
1178                         Tspi_Context_CloseObject(hContext, hMigPolicy);
1179                         return (result);
1180                 }
1181         }
1182 
1183         if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) {
1184                 result = set_legacy_key_params(*phKey);
1185                 if (result) {
1186                         Tspi_Context_CloseObject(hContext, *phKey);
1187                         Tspi_Context_CloseObject(hContext, hMigPolicy);
1188                         return (result);
1189                 }
1190         }
1191 
1192         if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) {
1193                 stlogit("Tspi_Key_CreateKey: 0x%0x - %s",
1194                     result, Trspi_Error_String(result));
1195                 Tspi_Context_CloseObject(hContext, *phKey);
1196                 Tspi_Context_CloseObject(hContext, hMigPolicy);
1197         }
1198 
1199         return (result);
1200 }
1201 
1202 static TSS_RESULT
1203 tss_change_auth(
1204         TSS_HCONTEXT hContext,
1205         TSS_HKEY hObjectToChange, TSS_HKEY hParentObject,
1206         TSS_UUID objUUID, TSS_UUID parentUUID,
1207         CK_CHAR *passHash)
1208 {
1209         TSS_RESULT result;
1210         TSS_HPOLICY hPolicy;
1211         TSS_HKEY oldkey;
1212 
1213         if ((result = Tspi_Context_CreateObject(hContext,
1214             TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) {
1215                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1216                     result, Trspi_Error_String(result));
1217                 return (result);
1218         }
1219 
1220         if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
1221             SHA1_DIGEST_LENGTH, passHash))) {
1222                 stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
1223                     result, Trspi_Error_String(result));
1224                 return (result);
1225         }
1226 
1227         if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject,
1228             hPolicy))) {
1229                 stlogit("Tspi_ChangeAuth: 0x%0x - %s",
1230                     result, Trspi_Error_String(result));
1231         }
1232         /*
1233          * Update the PS key by unregistering the key UUID and then
1234          * re-registering with the same UUID.  This forces the updated
1235          * auth data associated with the key to be stored in PS so
1236          * the new PIN can be used next time.
1237          */
1238         if ((result = Tspi_Context_UnregisterKey(hContext,
1239             TSS_PS_TYPE_USER, objUUID, &oldkey)))
1240                 stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s",
1241                     result, Trspi_Error_String(result));
1242 
1243         if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange,
1244             TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID)))
1245                 stlogit("Tspi_Context_RegisterKey: 0x%0x - %s",
1246                     result, Trspi_Error_String(result));
1247 
1248         return (result);
1249 }
1250 
1251 static CK_RV
1252 token_generate_leaf_key(TSS_HCONTEXT hContext,
1253         int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey)
1254 {
1255         CK_RV           rc = CKR_FUNCTION_FAILED;
1256         TSS_RESULT      result;
1257         TSS_HKEY        hParentKey;
1258         TSS_UUID        newuuid, parentUUID;
1259         char            *keyid;
1260         TSS_FLAG        initFlags = TSS_KEY_MIGRATABLE |
1261             TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048  | TSS_KEY_AUTHORIZATION;
1262 
1263         switch (key_type) {
1264                 case TPMTOK_PUBLIC_LEAF_KEY:
1265                         hParentKey = hPublicRootKey;
1266                         keyid = TPMTOK_PUBLIC_LEAF_KEY_ID;
1267                         local_uuid_copy(&parentUUID, &publicRootKeyUUID);
1268                         break;
1269                 case TPMTOK_PRIVATE_LEAF_KEY:
1270                         hParentKey = hPrivateRootKey;
1271                         keyid = TPMTOK_PRIVATE_LEAF_KEY_ID;
1272                         local_uuid_copy(&parentUUID, &privateRootKeyUUID);
1273                         break;
1274                 default:
1275                         stlogit("Unknown key type 0x%0x", key_type);
1276                         goto done;
1277         }
1278 
1279         if (result = tss_generate_key(hContext, initFlags, passHash,
1280             hParentKey, phKey)) {
1281                 return (rc);
1282         }
1283 
1284         /*
1285          * - generate newUUID
1286          * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1287          *   USER, newUUID, USER, parentUUID);
1288          * - store newUUID
1289          */
1290         (void) local_uuid_generate(&newuuid);
1291 
1292         result = Tspi_Context_RegisterKey(hContext, *phKey,
1293             TSS_PS_TYPE_USER, newuuid,
1294             TSS_PS_TYPE_USER, parentUUID);
1295         if (result == TSS_SUCCESS) {
1296                 int ret;
1297                 /*
1298                  * Add the UUID to the token UUID index.
1299                  */
1300                 ret = add_uuid(keyid, &newuuid);
1301 
1302                 if (ret)
1303                         result = Tspi_Context_UnregisterKey(hContext,
1304                             TSS_PS_TYPE_USER, newuuid, phKey);
1305                 else
1306                         rc = CKR_OK;
1307         }
1308 
1309 done:
1310         return (rc);
1311 }
1312 
1313 /*
1314  * PINs are verified by attempting to bind/unbind random data using a
1315  * TPM resident key that has the PIN being tested assigned as its "secret".
1316  * If the PIN is incorrect, the unbind operation will fail.
1317  */
1318 static CK_RV
1319 token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey)
1320 {
1321         TSS_HENCDATA hEncData;
1322         UINT32 ulUnboundDataLen;
1323         BYTE *rgbUnboundData = NULL;
1324         BYTE rgbData[16];
1325         TSS_RESULT result;
1326         CK_RV rc = CKR_FUNCTION_FAILED;
1327 
1328         if ((result = Tspi_Context_CreateObject(hContext,
1329             TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
1330                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
1331                     result, Trspi_Error_String(result));
1332                 goto done;
1333         }
1334 
1335         /* Use some random data */
1336         rc = token_rng(hContext, rgbData, sizeof (rgbData));
1337         if (rc)
1338                 goto done;
1339 
1340         if ((result = Tspi_Data_Bind(hEncData, hKey,
1341             sizeof (rgbData), rgbData))) {
1342                 stlogit("Tspi_Data_Bind: 0x%0x - %s",
1343                     result, Trspi_Error_String(result));
1344                 goto done;
1345         }
1346 
1347         /* unbind the junk data to test the key's auth data */
1348         result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen,
1349             &rgbUnboundData);
1350         if (result == TPM_E_AUTHFAIL) {
1351                 rc = CKR_PIN_INCORRECT;
1352                 stlogit("Tspi_Data_Unbind: 0x%0x - %s",
1353                     result, Trspi_Error_String(result));
1354                 goto done;
1355         } else if (result != TSS_SUCCESS) {
1356                 stlogit("Tspi_Data_Unbind: 0x%0x - %s",
1357                     result, Trspi_Error_String(result));
1358                 rc = CKR_FUNCTION_FAILED;
1359                 goto done;
1360         }
1361 
1362         if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen))
1363                 rc = CKR_PIN_INCORRECT;
1364         else
1365                 rc = CKR_OK;
1366 
1367 done:
1368         if (rgbUnboundData != NULL)
1369                 Tspi_Context_FreeMemory(hContext, rgbUnboundData);
1370         Tspi_Context_CloseObject(hContext, hEncData);
1371         return (rc);
1372 }
1373 
1374 static CK_RV
1375 token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
1376 {
1377         CK_RV           rc;
1378         TSS_RESULT      result;
1379         int             ret;
1380         TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
1381             TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
1382         TSS_UUID SRK_UUID = TSS_UUID_SRK;
1383         TSS_HKEY hSRK;
1384 
1385         if (token_load_srk(hContext, &hSRK))
1386                 return (CKR_FUNCTION_FAILED);
1387 
1388         /*
1389          * - create UUID privateRootKeyUUID
1390          * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1391          *   USER, privateRootKeyUUID, system, UUID_SRK);
1392          * - store privateRootKeyUUID in users private token space.
1393          */
1394         if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
1395             &hPrivateRootKey))) {
1396                 return (result);
1397         }
1398         if (local_uuid_is_null(&privateRootKeyUUID))
1399                 local_uuid_generate(&privateRootKeyUUID);
1400 
1401         result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey,
1402             TSS_PS_TYPE_USER, privateRootKeyUUID,
1403             TSS_PS_TYPE_SYSTEM, SRK_UUID);
1404 
1405         if (result) {
1406                 local_uuid_clear(&privateRootKeyUUID);
1407                 return (result);
1408         }
1409 
1410         ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID);
1411         if (ret) {
1412                 result = Tspi_Context_UnregisterKey(hContext,
1413                     TSS_PS_TYPE_USER, privateRootKeyUUID,
1414                     &hPrivateRootKey);
1415                 return (CKR_FUNCTION_FAILED);
1416         }
1417 
1418         if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) {
1419                 stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1420                     result, Trspi_Error_String(result));
1421                 Tspi_Context_CloseObject(hContext, hPrivateRootKey);
1422 
1423                 (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
1424                 local_uuid_clear(&privateRootKeyUUID);
1425 
1426                 hPrivateRootKey = NULL_HKEY;
1427                 return (CKR_FUNCTION_FAILED);
1428         }
1429 
1430 
1431         /* generate the private leaf key */
1432         if ((rc = token_generate_leaf_key(hContext,
1433             TPMTOK_PRIVATE_LEAF_KEY,
1434             pinHash, &hPrivateLeafKey))) {
1435                 return (rc);
1436         }
1437 
1438         if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) {
1439                 stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1440                     result, Trspi_Error_String(result));
1441 
1442                 (void) Tspi_Context_UnregisterKey(hContext,
1443                     TSS_PS_TYPE_USER, privateLeafKeyUUID,
1444                     &hPrivateLeafKey);
1445                 (void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID);
1446                 local_uuid_clear(&privateLeafKeyUUID);
1447 
1448                 (void) Tspi_Context_UnregisterKey(hContext,
1449                     TSS_PS_TYPE_USER, privateRootKeyUUID,
1450                     &hPrivateRootKey);
1451                 (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID);
1452                 local_uuid_clear(&privateRootKeyUUID);
1453 
1454                 Tspi_Context_CloseObject(hContext, hPrivateRootKey);
1455                 hPrivateRootKey = NULL_HKEY;
1456 
1457                 Tspi_Context_CloseObject(hContext, hPrivateLeafKey);
1458                 hPrivateRootKey = NULL_HKEY;
1459 
1460                 return (CKR_FUNCTION_FAILED);
1461         }
1462         return (rc);
1463 }
1464 
1465 static CK_RV
1466 token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash)
1467 {
1468         CK_RV           rc;
1469         TSS_RESULT      result;
1470         int             ret;
1471         TSS_FLAG initFlags = TSS_KEY_SIZE_2048 |
1472             TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE;
1473         TSS_UUID srk_uuid = TSS_UUID_SRK;
1474         TSS_HKEY hSRK;
1475 
1476         if (token_load_srk(hContext, &hSRK))
1477                 return (CKR_FUNCTION_FAILED);
1478 
1479         /*
1480          * - create publicRootKeyUUID
1481          * - Tspi_Context_RegisterKey(hContext, hPublicRootKey,
1482          *   USER, publicRootKeyUUID, system, UUID_SRK);
1483          * - store publicRootKeyUUID in users private token space.
1484          */
1485         if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK,
1486             &hPublicRootKey))) {
1487                 return (CKR_FUNCTION_FAILED);
1488         }
1489         if (local_uuid_is_null(&publicRootKeyUUID))
1490                 local_uuid_generate(&publicRootKeyUUID);
1491 
1492         result = Tspi_Context_RegisterKey(hContext, hPublicRootKey,
1493             TSS_PS_TYPE_USER, publicRootKeyUUID,
1494             TSS_PS_TYPE_SYSTEM, srk_uuid);
1495 
1496         if (result) {
1497                 local_uuid_clear(&publicRootKeyUUID);
1498                 return (CKR_FUNCTION_FAILED);
1499         }
1500 
1501         ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID);
1502         if (ret) {
1503                 result = Tspi_Context_UnregisterKey(hContext,
1504                     TSS_PS_TYPE_USER, publicRootKeyUUID,
1505                     &hPublicRootKey);
1506                 /* does result matter here? */
1507                 return (CKR_FUNCTION_FAILED);
1508         }
1509 
1510         /* Load the newly created publicRootKey into the TPM using the SRK */
1511         if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) {
1512                 stlogit("Tspi_Key_LoadKey: 0x%x - %s", result,
1513                     Trspi_Error_String(result));
1514                 Tspi_Context_CloseObject(hContext, hPublicRootKey);
1515                 hPublicRootKey = NULL_HKEY;
1516                 return (CKR_FUNCTION_FAILED);
1517         }
1518 
1519         /* create the SO's leaf key */
1520         if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY,
1521             pinHash, &hPublicLeafKey))) {
1522                 return (rc);
1523         }
1524 
1525         if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) {
1526                 stlogit("Tspi_Key_LoadKey: 0x%0x - %s",
1527                     result, Trspi_Error_String(result));
1528 
1529                 /* Unregister keys and clear UUIDs */
1530                 (void) Tspi_Context_UnregisterKey(hContext,
1531                     TSS_PS_TYPE_USER, publicLeafKeyUUID,
1532                     &hPublicLeafKey);
1533                 (void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID);
1534 
1535                 (void) Tspi_Context_UnregisterKey(hContext,
1536                     TSS_PS_TYPE_USER, publicRootKeyUUID,
1537                     &hPublicRootKey);
1538                 (void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID);
1539 
1540                 Tspi_Context_CloseObject(hContext, hPublicRootKey);
1541                 hPublicRootKey = NULL_HKEY;
1542 
1543                 Tspi_Context_CloseObject(hContext, hPublicLeafKey);
1544                 hPublicLeafKey = NULL_HKEY;
1545 
1546                 return (CKR_FUNCTION_FAILED);
1547         }
1548 
1549         return (rc);
1550 }
1551 
1552 CK_RV
1553 token_specific_login(
1554         TSS_HCONTEXT hContext,
1555         CK_USER_TYPE userType,
1556         CK_CHAR_PTR pPin,
1557         CK_ULONG ulPinLen)
1558 {
1559         CK_RV rc;
1560         CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1561         TSS_RESULT result;
1562         TSS_HKEY hSRK;
1563 
1564         /* Make sure the SRK is loaded into the TPM */
1565         if ((result = token_load_srk(hContext, &hSRK))) {
1566                 return (CKR_FUNCTION_FAILED);
1567         }
1568 
1569         if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
1570                 return (CKR_FUNCTION_FAILED);
1571         }
1572 
1573         if (userType == CKU_USER) {
1574                 /*
1575                  * If the public root key doesn't exist yet,
1576                  * the SO hasn't init'd the token.
1577                  */
1578                 if ((result = token_load_public_root_key(hContext))) {
1579                         if (result == TPM_E_DECRYPT_ERROR) {
1580                                 return (CKR_USER_PIN_NOT_INITIALIZED);
1581                         }
1582                 }
1583 
1584                 /*
1585                  * - find privateRootKeyUUID
1586                  * - load by UUID (SRK parent)
1587                  */
1588                 if (local_uuid_is_null(&privateRootKeyUUID) &&
1589                     find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID,
1590                     &privateRootKeyUUID)) {
1591                                 if (memcmp(hash_sha,
1592                                     default_user_pin_sha,
1593                                     SHA1_DIGEST_LENGTH))
1594                                         return (CKR_PIN_INCORRECT);
1595 
1596                                 not_initialized = 1;
1597                                 return (CKR_OK);
1598                 }
1599 
1600                 if ((rc = verify_user_pin(hContext, hash_sha))) {
1601                         return (rc);
1602                 }
1603 
1604                 (void) memcpy(current_user_pin_sha, hash_sha,
1605                     SHA1_DIGEST_LENGTH);
1606 
1607                 rc = load_private_token_objects(hContext);
1608                 if (rc == CKR_OK) {
1609                         (void) XProcLock(xproclock);
1610                         global_shm->priv_loaded = TRUE;
1611                         (void) XProcUnLock(xproclock);
1612                 }
1613         } else {
1614                 /*
1615                  * SO login logic:
1616                  *
1617                  * - find publicRootKey UUID
1618                  * - load by UUID wrap with hSRK from above
1619                  */
1620                 if (local_uuid_is_null(&publicRootKeyUUID) &&
1621                     find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID,
1622                     &publicRootKeyUUID)) {
1623                                 if (memcmp(hash_sha,
1624                                     default_so_pin_sha,
1625                                     SHA1_DIGEST_LENGTH))
1626                                         return (CKR_PIN_INCORRECT);
1627 
1628                                 not_initialized = 1;
1629                                 return (CKR_OK);
1630 
1631                 }
1632                 if (hPublicRootKey == NULL_HKEY) {
1633                         result = tss_find_and_load_key(
1634                             hContext,
1635                             TPMTOK_PUBLIC_ROOT_KEY_ID,
1636                             &publicRootKeyUUID, hSRK, NULL,
1637                             &hPublicRootKey);
1638 
1639                         if (result)
1640                                 return (CKR_FUNCTION_FAILED);
1641                 }
1642 
1643                 /* find, load the public leaf key */
1644                 if (hPublicLeafKey == NULL_HKEY) {
1645                         result = tss_find_and_load_key(
1646                             hContext,
1647                             TPMTOK_PUBLIC_LEAF_KEY_ID,
1648                             &publicLeafKeyUUID, hPublicRootKey, hash_sha,
1649                             &hPublicLeafKey);
1650                         if (result)
1651                                 return (CKR_FUNCTION_FAILED);
1652                 }
1653 
1654                 if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
1655                         return (rc);
1656                 }
1657 
1658                 (void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH);
1659         }
1660 
1661         return (rc);
1662 }
1663 
1664 CK_RV
1665 token_specific_logout(TSS_HCONTEXT hContext)
1666 {
1667         if (hPrivateLeafKey != NULL_HKEY) {
1668                 Tspi_Key_UnloadKey(hPrivateLeafKey);
1669                 hPrivateLeafKey = NULL_HKEY;
1670         } else if (hPublicLeafKey != NULL_HKEY) {
1671                 Tspi_Key_UnloadKey(hPublicLeafKey);
1672                 hPublicLeafKey = NULL_HKEY;
1673         }
1674 
1675         local_uuid_clear(&publicRootKeyUUID);
1676         local_uuid_clear(&publicLeafKeyUUID);
1677         local_uuid_clear(&privateRootKeyUUID);
1678         local_uuid_clear(&privateLeafKeyUUID);
1679 
1680         (void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH);
1681         (void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH);
1682 
1683         (void) object_mgr_purge_private_token_objects(hContext);
1684 
1685         return (CKR_OK);
1686 }
1687 
1688 /*ARGSUSED*/
1689 CK_RV
1690 token_specific_init_pin(TSS_HCONTEXT hContext,
1691         CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
1692 {
1693         /*
1694          * Since the SO must log in before calling C_InitPIN, we will
1695          * be able to return (CKR_OK) automatically here.
1696          * This is because the USER key structure is created at the
1697          * time of their first login, not at C_InitPIN time.
1698          */
1699         return (CKR_OK);
1700 }
1701 
1702 static CK_RV
1703 check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash,
1704         CK_ULONG ulPinLen)
1705 {
1706         /* make sure the new PIN is different */
1707         if (userType == CKU_USER) {
1708                 if (!memcmp(pinHash, default_user_pin_sha,
1709                     SHA1_DIGEST_LENGTH)) {
1710                         LogError1("new PIN must not be the default");
1711                         return (CKR_PIN_INVALID);
1712                 }
1713         } else {
1714                 if (!memcmp(pinHash, default_so_pin_sha,
1715                     SHA1_DIGEST_LENGTH)) {
1716                         LogError1("new PIN must not be the default");
1717                         return (CKR_PIN_INVALID);
1718                 }
1719         }
1720 
1721         if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) {
1722                 LogError1("New PIN is out of size range");
1723                 return (CKR_PIN_LEN_RANGE);
1724         }
1725 
1726         return (CKR_OK);
1727 }
1728 
1729 /*
1730  * This function is called from set_pin only, where a non-logged-in public
1731  * session can provide the user pin which must be verified. This function
1732  * assumes that the pin has already been set once, so there's no migration
1733  * path option or checking of the default user pin.
1734  */
1735 static CK_RV
1736 verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha)
1737 {
1738         CK_RV rc;
1739         TSS_RESULT result;
1740         TSS_HKEY hSRK;
1741 
1742         if (token_load_srk(hContext, &hSRK))
1743                 return (CKR_FUNCTION_FAILED);
1744 
1745         /*
1746          * Verify the user by loading the privateLeafKey
1747          * into the TPM (if it's not already) and then
1748          * call the verify_pin operation.
1749          *
1750          * The hashed PIN is assigned to the private leaf key.
1751          * If it is incorrect (not the same as the one originally
1752          * used when the key was created), the verify operation
1753          * will fail.
1754          */
1755         if (hPrivateRootKey == NULL_HKEY) {
1756                 result = tss_find_and_load_key(
1757                     hContext,
1758                     TPMTOK_PRIVATE_ROOT_KEY_ID,
1759                     &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey);
1760                 if (result)
1761                         return (CKR_FUNCTION_FAILED);
1762         }
1763 
1764         if (hPrivateLeafKey == NULL_HKEY) {
1765                 result = tss_find_and_load_key(
1766                     hContext,
1767                     TPMTOK_PRIVATE_LEAF_KEY_ID,
1768                     &privateLeafKeyUUID, hPrivateRootKey, hash_sha,
1769                     &hPrivateLeafKey);
1770 
1771                 if (result)
1772                         return (CKR_FUNCTION_FAILED);
1773         }
1774 
1775         /*
1776          * Verify that the PIN is correct by attempting to wrap/unwrap some
1777          * random data.
1778          */
1779         if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) {
1780                 return (rc);
1781         }
1782 
1783         return (CKR_OK);
1784 }
1785 
1786 CK_RV
1787 token_specific_set_pin(ST_SESSION_HANDLE session,
1788         CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen,
1789         CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen)
1790 {
1791         SESSION         *sess = session_mgr_find(session.sessionh);
1792         CK_BYTE         oldpin_hash[SHA1_DIGEST_LENGTH];
1793         CK_BYTE         newpin_hash[SHA1_DIGEST_LENGTH];
1794         CK_RV           rc;
1795         TSS_HKEY        hSRK;
1796 
1797         if (!sess) {
1798                 return (CKR_SESSION_HANDLE_INVALID);
1799         }
1800 
1801         if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) {
1802                 return (CKR_FUNCTION_FAILED);
1803         }
1804         if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) {
1805                 return (CKR_FUNCTION_FAILED);
1806         }
1807 
1808         if (token_load_srk(sess->hContext, &hSRK)) {
1809                 return (CKR_FUNCTION_FAILED);
1810         }
1811 
1812         /*
1813          * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of
1814          * the user that is currently logged in, or the CKU_USER PIN
1815          * if the session is not logged in."
1816          * A non R/W session fails with CKR_SESSION_READ_ONLY.
1817          */
1818         if (sess->session_info.state == CKS_RW_USER_FUNCTIONS ||
1819             sess->session_info.state == CKS_RW_PUBLIC_SESSION) {
1820                 if (not_initialized) {
1821                         if (memcmp(oldpin_hash, default_user_pin_sha,
1822                             SHA1_DIGEST_LENGTH)) {
1823                                 return (CKR_PIN_INCORRECT);
1824                         }
1825 
1826                         if ((rc = check_pin_properties(CKU_USER, newpin_hash,
1827                             ulNewPinLen))) {
1828                                 return (rc);
1829                         }
1830 
1831                         if ((rc = token_create_private_tree(sess->hContext,
1832                             newpin_hash))) {
1833                                 return (CKR_FUNCTION_FAILED);
1834                         }
1835 
1836                         nv_token_data->token_info.flags &=
1837                             ~(CKF_USER_PIN_TO_BE_CHANGED);
1838                         nv_token_data->token_info.flags |=
1839                             CKF_USER_PIN_INITIALIZED;
1840 
1841                         nv_token_data->token_info.flags &=
1842                             ~(CKF_USER_PIN_TO_BE_CHANGED);
1843                         nv_token_data->token_info.flags |=
1844                             CKF_USER_PIN_INITIALIZED;
1845 
1846                         return (save_token_data(nv_token_data));
1847                 }
1848 
1849                 if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) {
1850                         /* if we're already logged in, just verify the hash */
1851                         if (memcmp(current_user_pin_sha, oldpin_hash,
1852                             SHA1_DIGEST_LENGTH)) {
1853                                 return (CKR_PIN_INCORRECT);
1854                         }
1855                 } else {
1856                         if ((rc = verify_user_pin(sess->hContext,
1857                             oldpin_hash))) {
1858                                 return (rc);
1859                         }
1860                 }
1861 
1862                 if ((rc = check_pin_properties(CKU_USER, newpin_hash,
1863                     ulNewPinLen)))
1864                         return (rc);
1865 
1866                 /* change the auth on the TSS object */
1867                 if (tss_change_auth(sess->hContext,
1868                     hPrivateLeafKey, hPrivateRootKey,
1869                     privateLeafKeyUUID, privateRootKeyUUID,
1870                     newpin_hash))
1871                         return (CKR_FUNCTION_FAILED);
1872 
1873         } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
1874                 if (not_initialized) {
1875                         if (memcmp(default_so_pin_sha, oldpin_hash,
1876                             SHA1_DIGEST_LENGTH))
1877                                 return (CKR_PIN_INCORRECT);
1878 
1879                         if ((rc = check_pin_properties(CKU_SO,
1880                             newpin_hash, ulNewPinLen)))
1881                                 return (rc);
1882 
1883                         if ((rc = token_create_public_tree(sess->hContext,
1884                             newpin_hash)))
1885                                 return (CKR_FUNCTION_FAILED);
1886 
1887                         nv_token_data->token_info.flags &=
1888                             ~(CKF_SO_PIN_TO_BE_CHANGED);
1889 
1890                         return (save_token_data(nv_token_data));
1891                 }
1892 
1893                 if (memcmp(current_so_pin_sha, oldpin_hash,
1894                     SHA1_DIGEST_LENGTH))
1895                         return (CKR_PIN_INCORRECT);
1896 
1897                 if ((rc = check_pin_properties(CKU_SO, newpin_hash,
1898                     ulNewPinLen)))
1899                         return (rc);
1900 
1901                 /* change auth on the SO's leaf key */
1902                 if (tss_change_auth(sess->hContext,
1903                     hPublicLeafKey, hPublicRootKey,
1904                     publicLeafKeyUUID, publicRootKeyUUID,
1905                     newpin_hash))
1906                         return (CKR_FUNCTION_FAILED);
1907 
1908         } else {
1909                 rc = CKR_SESSION_READ_ONLY;
1910         }
1911 
1912         return (rc);
1913 }
1914 
1915 /* only called at token init time */
1916 CK_RV
1917 token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin,
1918     CK_ULONG ulPinLen)
1919 {
1920         CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
1921         CK_RV rc;
1922         TSS_RESULT result;
1923         TSS_HKEY hSRK;
1924 
1925         if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) {
1926                 return (CKR_FUNCTION_FAILED);
1927         }
1928         if ((rc = token_load_srk(hContext, &hSRK))) {
1929                 return (CKR_FUNCTION_FAILED);
1930         }
1931 
1932         /*
1933          * TRYME INSTEAD:
1934          * - find publicRootKeyUUID
1935          * - Load publicRootKey by UUID (SRK parent)
1936          * - find publicLeafKeyUUID
1937          * - Load publicLeafKey by UUID (publicRootKey parent)
1938          * - set password policy on publicLeafKey
1939          */
1940         if (local_uuid_is_null(&publicRootKeyUUID) &&
1941             find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) {
1942                 /*
1943                  * The SO hasn't set their PIN yet, compare the
1944                  * login pin with the hard-coded value.
1945                  */
1946                 if (memcmp(default_so_pin_sha, hash_sha,
1947                     SHA1_DIGEST_LENGTH)) {
1948                         return (CKR_PIN_INCORRECT);
1949                 }
1950                 return (CKR_OK);
1951         }
1952 
1953         result = Tspi_Context_GetKeyByUUID(hContext,
1954             TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey);
1955 
1956         if (result)
1957                 return (CKR_FUNCTION_FAILED);
1958 
1959         result = Tspi_Key_LoadKey(hPublicRootKey, hSRK);
1960         if (result)
1961                 return (CKR_FUNCTION_FAILED);
1962 
1963         if (local_uuid_is_null(&publicLeafKeyUUID) &&
1964             find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID))
1965                 return (CKR_FUNCTION_FAILED);
1966 
1967         result = Tspi_Context_GetKeyByUUID(hContext,
1968             TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey);
1969         if (result)
1970                 return (CKR_FUNCTION_FAILED);
1971 
1972         result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE,
1973             hPublicLeafKey, hash_sha);
1974         if (result)
1975                 return (CKR_FUNCTION_FAILED);
1976 
1977         result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey);
1978         if (result)
1979                 return (CKR_FUNCTION_FAILED);
1980 
1981         /* If the hash given is wrong, the verify will fail */
1982         if ((rc = token_verify_pin(hContext, hPublicLeafKey))) {
1983                 return (rc);
1984         }
1985 
1986         return (CKR_OK);
1987 }
1988 
1989 CK_RV
1990 token_specific_final(TSS_HCONTEXT hContext)
1991 {
1992         if (hPublicRootKey != NULL_HKEY) {
1993                 Tspi_Context_CloseObject(hContext, hPublicRootKey);
1994                 hPublicRootKey = NULL_HKEY;
1995         }
1996         if (hPublicLeafKey != NULL_HKEY) {
1997                 Tspi_Context_CloseObject(hContext, hPublicLeafKey);
1998                 hPublicLeafKey = NULL_HKEY;
1999         }
2000         if (hPrivateRootKey != NULL_HKEY) {
2001                 Tspi_Context_CloseObject(hContext, hPrivateRootKey);
2002                 hPrivateRootKey = NULL_HKEY;
2003         }
2004         if (hPrivateLeafKey != NULL_HKEY) {
2005                 Tspi_Context_CloseObject(hContext, hPrivateLeafKey);
2006                 hPrivateLeafKey = NULL_HKEY;
2007         }
2008         return (CKR_OK);
2009 }
2010 
2011 /*
2012  * Wrap the 20 bytes of auth data and store in an attribute of the two
2013  * keys.
2014  */
2015 static CK_RV
2016 token_wrap_auth_data(TSS_HCONTEXT hContext,
2017         CK_BYTE *authData, TEMPLATE *publ_tmpl,
2018         TEMPLATE *priv_tmpl)
2019 {
2020         CK_RV           rc;
2021         CK_ATTRIBUTE    *new_attr;
2022 
2023         TSS_RESULT      ret;
2024         TSS_HKEY        hParentKey;
2025         TSS_HENCDATA    hEncData;
2026         BYTE            *blob;
2027         UINT32          blob_size;
2028 
2029         if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) {
2030                 return (CKR_FUNCTION_FAILED);
2031         } else if (hPublicLeafKey != NULL_HKEY) {
2032                 hParentKey = hPublicLeafKey;
2033         } else {
2034                 hParentKey = hPrivateLeafKey;
2035         }
2036 
2037         /* create the encrypted data object */
2038         if ((ret = Tspi_Context_CreateObject(hContext,
2039             TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2040                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2041                     ret, Trspi_Error_String(ret));
2042                 return (CKR_FUNCTION_FAILED);
2043         }
2044 
2045         if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH,
2046             authData))) {
2047                 stlogit("Tspi_Data_Bind: 0x%0x - %s",
2048                     ret, Trspi_Error_String(ret));
2049                 return (CKR_FUNCTION_FAILED);
2050         }
2051 
2052         /* pull the encrypted data out of the encrypted data object */
2053         if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB,
2054             TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) {
2055                 stlogit("Tspi_SetAttribData: 0x%0x - %s",
2056                     ret, Trspi_Error_String(ret));
2057                 return (CKR_FUNCTION_FAILED);
2058         }
2059 
2060         if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size,
2061             &new_attr))) {
2062                 return (rc);
2063         }
2064         (void) template_update_attribute(publ_tmpl, new_attr);
2065 
2066         if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob,
2067             blob_size, &new_attr))) {
2068                 return (rc);
2069         }
2070         (void) template_update_attribute(priv_tmpl, new_attr);
2071 
2072         return (rc);
2073 }
2074 
2075 static CK_RV
2076 token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData,
2077         CK_ULONG encAuthDataLen, TSS_HKEY hKey,
2078         BYTE **authData)
2079 {
2080         TSS_RESULT      result;
2081         TSS_HENCDATA    hEncData;
2082         BYTE            *buf;
2083         UINT32          buf_size;
2084 
2085         if ((result = Tspi_Context_CreateObject(hContext,
2086             TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2087                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2088                     result, Trspi_Error_String(result));
2089                 return (CKR_FUNCTION_FAILED);
2090         }
2091 
2092         if ((result = Tspi_SetAttribData(hEncData,
2093             TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2094             encAuthDataLen, encAuthData))) {
2095                 stlogit("Tspi_SetAttribData: 0x%0x - %s",
2096                     result, Trspi_Error_String(result));
2097                 return (CKR_FUNCTION_FAILED);
2098         }
2099 
2100         /* unbind the data, receiving the plaintext back */
2101         if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) {
2102                 stlogit("Tspi_Data_Unbind: 0x%0x - %s",
2103                     result, Trspi_Error_String(result));
2104                 return (CKR_FUNCTION_FAILED);
2105         }
2106 
2107         if (buf_size != SHA1_DIGEST_LENGTH) {
2108                 return (CKR_FUNCTION_FAILED);
2109         }
2110 
2111         *authData = buf;
2112 
2113         return (CKR_OK);
2114 }
2115 
2116 CK_RV
2117 token_specific_rsa_generate_keypair(
2118         TSS_HCONTEXT hContext,
2119         TEMPLATE  *publ_tmpl,
2120         TEMPLATE  *priv_tmpl)
2121 {
2122         CK_ATTRIBUTE    *attr = NULL;
2123         CK_ULONG        mod_bits = 0;
2124         CK_BBOOL        flag;
2125         CK_RV           rc;
2126 
2127         TSS_FLAG        initFlags = 0;
2128         BYTE            authHash[SHA1_DIGEST_LENGTH];
2129         BYTE            *authData = NULL;
2130         TSS_HKEY        hKey = NULL_HKEY;
2131         TSS_HKEY        hParentKey = NULL_HKEY;
2132         TSS_RESULT      result;
2133         UINT32          ulBlobLen;
2134         BYTE            *rgbBlob;
2135 
2136         /* Make sure the public exponent is usable */
2137         if ((util_check_public_exponent(publ_tmpl))) {
2138                 return (CKR_TEMPLATE_INCONSISTENT);
2139         }
2140 
2141         flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr);
2142         if (!flag) {
2143                 return (CKR_TEMPLATE_INCOMPLETE);
2144         }
2145         mod_bits = *(CK_ULONG *)attr->pValue;
2146 
2147         if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) {
2148                 return (CKR_KEY_SIZE_RANGE);
2149         }
2150 
2151         /*
2152          * If we're not logged in, hPrivateLeafKey and hPublicLeafKey
2153          * should be NULL.
2154          */
2155         if ((hPrivateLeafKey == NULL_HKEY) &&
2156             (hPublicLeafKey == NULL_HKEY)) {
2157                 /* public session, wrap key with the PRK */
2158                 initFlags |= TSS_KEY_TYPE_LEGACY |
2159                     TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2160 
2161                 if ((result = token_load_public_root_key(hContext))) {
2162                         return (CKR_FUNCTION_FAILED);
2163                 }
2164 
2165                 hParentKey = hPublicRootKey;
2166         } else if (hPrivateLeafKey != NULL_HKEY) {
2167                 /* logged in USER session */
2168                 initFlags |= TSS_KEY_TYPE_LEGACY |
2169                     TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2170 
2171                 /* get a random SHA1 hash for the auth data */
2172                 if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
2173                         return (CKR_FUNCTION_FAILED);
2174                 }
2175 
2176                 authData = authHash;
2177                 hParentKey = hPrivateRootKey;
2178         } else {
2179                 /* logged in SO session */
2180                 initFlags |= TSS_KEY_TYPE_LEGACY |
2181                     TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE;
2182 
2183                 /* get a random SHA1 hash for the auth data */
2184                 if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) {
2185                         return (CKR_FUNCTION_FAILED);
2186                 }
2187 
2188                 authData = authHash;
2189                 hParentKey = hPublicRootKey;
2190         }
2191 
2192         if ((result = tss_generate_key(hContext, initFlags, authData,
2193             hParentKey, &hKey))) {
2194                 return (result);
2195         }
2196 
2197         if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
2198             TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) {
2199                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
2200                     result, Trspi_Error_String(result));
2201                 return (CKR_FUNCTION_FAILED);
2202         }
2203 
2204         if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
2205             ulBlobLen, &attr))) {
2206                 Tspi_Context_FreeMemory(hContext, rgbBlob);
2207                 return (rc);
2208         }
2209         (void) template_update_attribute(priv_tmpl, attr);
2210         if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob,
2211             ulBlobLen, &attr))) {
2212                 Tspi_Context_FreeMemory(hContext, rgbBlob);
2213                 return (rc);
2214         }
2215         (void) template_update_attribute(publ_tmpl, attr);
2216 
2217         Tspi_Context_FreeMemory(hContext, rgbBlob);
2218 
2219         /* grab the public key to put into the public key object */
2220         if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2221             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) {
2222                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
2223                     result, Trspi_Error_String(result));
2224                 return (result);
2225         }
2226 
2227         /* add the public key blob to the object template */
2228         if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
2229                 Tspi_Context_FreeMemory(hContext, rgbBlob);
2230                 return (rc);
2231         }
2232         (void) template_update_attribute(publ_tmpl, attr);
2233 
2234         /* add the public key blob to the object template */
2235         if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) {
2236                 Tspi_Context_FreeMemory(hContext, rgbBlob);
2237                 return (rc);
2238         }
2239         (void) template_update_attribute(priv_tmpl, attr);
2240         Tspi_Context_FreeMemory(hContext, rgbBlob);
2241 
2242         /* wrap the authdata and put it into an object */
2243         if (authData != NULL) {
2244                 rc = token_wrap_auth_data(hContext, authData, publ_tmpl,
2245                     priv_tmpl);
2246         }
2247 
2248         return (rc);
2249 }
2250 
2251 static CK_RV
2252 token_rsa_load_key(
2253         TSS_HCONTEXT hContext,
2254         OBJECT *key_obj,
2255         TSS_HKEY *phKey)
2256 {
2257         TSS_RESULT result;
2258         TSS_HPOLICY hPolicy = NULL_HPOLICY;
2259         TSS_HKEY        hParentKey;
2260         BYTE            *authData = NULL;
2261         CK_ATTRIBUTE    *attr;
2262         CK_RV           rc;
2263         CK_OBJECT_HANDLE handle;
2264         CK_ULONG        class;
2265 
2266         if (hPrivateLeafKey != NULL_HKEY) {
2267                 hParentKey = hPrivateRootKey;
2268         } else {
2269                 if ((result = token_load_public_root_key(hContext)))
2270                         return (CKR_FUNCTION_FAILED);
2271 
2272                 hParentKey = hPublicRootKey;
2273         }
2274 
2275         *phKey = NULL;
2276         if (template_attribute_find(key_obj->template, CKA_CLASS,
2277             &attr) == FALSE) {
2278                 return (CKR_TEMPLATE_INCOMPLETE);
2279         }
2280         class = *((CK_ULONG *)attr->pValue);
2281 
2282         rc = template_attribute_find(key_obj->template,
2283             CKA_IBM_OPAQUE, &attr);
2284         /*
2285          * A public key cannot use the OPAQUE data attribute so they
2286          * must be created in software.  A private key may not yet
2287          * have its "opaque" data defined and needs to be created
2288          * and loaded so it can be used inside the TPM.
2289          */
2290         if (class == CKO_PUBLIC_KEY || rc == FALSE) {
2291                 rc = object_mgr_find_in_map2(hContext, key_obj, &handle);
2292                 if (rc != CKR_OK)
2293                         return (CKR_FUNCTION_FAILED);
2294 
2295                 if ((rc = token_load_key(hContext,
2296                     handle, hParentKey, NULL, phKey))) {
2297                         return (rc);
2298                 }
2299         }
2300         /*
2301          * If this is a private key, get the blob and load it in the TPM.
2302          * If it is public, the key is already loaded in software.
2303          */
2304         if (class == CKO_PRIVATE_KEY) {
2305                 /* If we already have a handle, just load it */
2306                 if (*phKey != NULL) {
2307                         result = Tspi_Key_LoadKey(*phKey, hParentKey);
2308                         if (result) {
2309                                 stlogit("Tspi_Context_LoadKeyByBlob: "
2310                                     "0x%0x - %s",
2311                                     result, Trspi_Error_String(result));
2312                                 return (CKR_FUNCTION_FAILED);
2313                         }
2314                 } else {
2315                         /* try again to get the CKA_IBM_OPAQUE attr */
2316                         if ((rc = template_attribute_find(key_obj->template,
2317                             CKA_IBM_OPAQUE, &attr)) == FALSE) {
2318                                 return (rc);
2319                         }
2320                         if ((result = Tspi_Context_LoadKeyByBlob(hContext,
2321                             hParentKey, attr->ulValueLen, attr->pValue,
2322                             phKey))) {
2323                                 stlogit("Tspi_Context_LoadKeyByBlob: "
2324                                     "0x%0x - %s",
2325                                     result, Trspi_Error_String(result));
2326                                 return (CKR_FUNCTION_FAILED);
2327                         }
2328                 }
2329         }
2330 
2331         /* auth data may be required */
2332         if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA,
2333             &attr) == TRUE && attr) {
2334                 if ((hPrivateLeafKey == NULL_HKEY) &&
2335                     (hPublicLeafKey == NULL_HKEY)) {
2336                         return (CKR_FUNCTION_FAILED);
2337                 } else if (hPublicLeafKey != NULL_HKEY) {
2338                         hParentKey = hPublicLeafKey;
2339                 } else {
2340                         hParentKey = hPrivateLeafKey;
2341                 }
2342 
2343                 if ((result = token_unwrap_auth_data(hContext,
2344                     attr->pValue, attr->ulValueLen,
2345                     hParentKey, &authData))) {
2346                         return (CKR_FUNCTION_FAILED);
2347                 }
2348 
2349                 if ((result = Tspi_GetPolicyObject(*phKey,
2350                     TSS_POLICY_USAGE, &hPolicy))) {
2351                         stlogit("Tspi_GetPolicyObject: 0x%0x - %s",
2352                             result, Trspi_Error_String(result));
2353                         return (CKR_FUNCTION_FAILED);
2354                 }
2355 
2356                 /*
2357                  * If the policy handle returned is the same as the
2358                  * context's default policy, then a new policy must
2359                  * be created and assigned to the key. Otherwise, just set the
2360                  * secret in the policy.
2361                  */
2362                 if (hPolicy == hDefaultPolicy) {
2363                         if ((result = Tspi_Context_CreateObject(hContext,
2364                             TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
2365                             &hPolicy))) {
2366                                 stlogit("Tspi_Context_CreateObject: "
2367                                     "0x%0x - %s",
2368                                     result, Trspi_Error_String(result));
2369                                 return (CKR_FUNCTION_FAILED);
2370                         }
2371 
2372                         if ((result = Tspi_Policy_SetSecret(hPolicy,
2373                             TSS_SECRET_MODE_SHA1,
2374                             SHA1_DIGEST_LENGTH, authData))) {
2375                                 stlogit("Tspi_Policy_SetSecret: "
2376                                     "0x%0x - %s",
2377                                     result, Trspi_Error_String(result));
2378                                 return (CKR_FUNCTION_FAILED);
2379                         }
2380 
2381                         if ((result = Tspi_Policy_AssignToObject(hPolicy,
2382                             *phKey))) {
2383                                 stlogit("Tspi_Policy_AssignToObject: "
2384                                     "0x%0x - %s",
2385                                     result, Trspi_Error_String(result));
2386                                 return (CKR_FUNCTION_FAILED);
2387                         }
2388                 } else if ((result = Tspi_Policy_SetSecret(hPolicy,
2389                     TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) {
2390                         stlogit("Tspi_Policy_SetSecret: 0x%0x - %s",
2391                             result, Trspi_Error_String(result));
2392                         return (CKR_FUNCTION_FAILED);
2393                 }
2394 
2395                 Tspi_Context_FreeMemory(hContext, authData);
2396         }
2397 
2398         return (CKR_OK);
2399 }
2400 
2401 CK_RV
2402 tpm_decrypt_data(
2403         TSS_HCONTEXT hContext,
2404         TSS_HKEY    hKey,
2405         CK_BYTE   * in_data,
2406         CK_ULONG    in_data_len,
2407         CK_BYTE   * out_data,
2408         CK_ULONG  * out_data_len)
2409 {
2410         TSS_RESULT result;
2411         TSS_HENCDATA    hEncData = NULL_HENCDATA;
2412         UINT32          buf_size = 0, modLen;
2413         BYTE            *buf = NULL, *modulus = NULL;
2414         CK_ULONG        chunklen, remain, outlen;
2415 
2416         /* push the data into the encrypted data object */
2417         if ((result = Tspi_Context_CreateObject(hContext,
2418             TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2419                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2420                     result, Trspi_Error_String(result));
2421                 return (CKR_FUNCTION_FAILED);
2422         }
2423 
2424         /*
2425          * Figure out the modulus size so we can break the data
2426          * into smaller chunks if necessary.
2427          */
2428         if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2429             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2430                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
2431                     result, Trspi_Error_String(result));
2432                 return (result);
2433         }
2434         /* we don't need the actual modulus */
2435         Tspi_Context_FreeMemory(hContext, modulus);
2436 
2437         chunklen = (in_data_len > modLen ? modLen : in_data_len);
2438         remain = in_data_len;
2439         outlen = 0;
2440 
2441         while (remain > 0) {
2442                 if ((result = Tspi_SetAttribData(hEncData,
2443                     TSS_TSPATTRIB_ENCDATA_BLOB,
2444                     TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2445                     chunklen, in_data))) {
2446                         stlogit("Tspi_SetAttribData: 0x%0x - %s",
2447                             result, Trspi_Error_String(result));
2448                         return (CKR_FUNCTION_FAILED);
2449                 }
2450 
2451                 /* unbind the data, receiving the plaintext back */
2452                 if ((result = Tspi_Data_Unbind(hEncData, hKey,
2453                     &buf_size, &buf))) {
2454                         stlogit("Tspi_Data_Unbind: 0x%0x - %s",
2455                             result, Trspi_Error_String(result));
2456                         return (CKR_FUNCTION_FAILED);
2457                 }
2458 
2459                 if (*out_data_len < buf_size + outlen) {
2460                         Tspi_Context_FreeMemory(hContext, buf);
2461                         return (CKR_BUFFER_TOO_SMALL);
2462                 }
2463 
2464                 (void) memcpy(out_data + outlen, buf, buf_size);
2465 
2466                 outlen += buf_size;
2467                 in_data += chunklen;
2468                 remain -= chunklen;
2469 
2470                 Tspi_Context_FreeMemory(hContext, buf);
2471                 if (chunklen > remain)
2472                         chunklen = remain;
2473         }
2474         *out_data_len = outlen;
2475         return (CKR_OK);
2476 }
2477 
2478 CK_RV
2479 token_specific_rsa_decrypt(
2480         TSS_HCONTEXT hContext,
2481         CK_BYTE   * in_data,
2482         CK_ULONG    in_data_len,
2483         CK_BYTE   * out_data,
2484         CK_ULONG  * out_data_len,
2485         OBJECT    * key_obj)
2486 {
2487         CK_RV           rc;
2488         TSS_HKEY        hKey;
2489 
2490         if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2491                 return (rc);
2492         }
2493 
2494         rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len,
2495             out_data, out_data_len);
2496 
2497         return (rc);
2498 }
2499 
2500 CK_RV
2501 token_specific_rsa_verify(
2502         TSS_HCONTEXT hContext,
2503         CK_BYTE   * in_data,
2504         CK_ULONG    in_data_len,
2505         CK_BYTE   * sig,
2506         CK_ULONG    sig_len,
2507         OBJECT    * key_obj)
2508 {
2509         TSS_RESULT      result;
2510         TSS_HHASH       hHash;
2511         TSS_HKEY        hKey;
2512         CK_RV           rc;
2513 
2514         if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2515                 return (rc);
2516         }
2517 
2518         /* Create the hash object we'll use to sign */
2519         if ((result = Tspi_Context_CreateObject(hContext,
2520             TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
2521                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2522                     result, Trspi_Error_String(result));
2523                 return (CKR_FUNCTION_FAILED);
2524         }
2525 
2526         /* Insert the data into the hash object */
2527         if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
2528             in_data))) {
2529                 stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
2530                     result, Trspi_Error_String(result));
2531                 return (CKR_FUNCTION_FAILED);
2532         }
2533 
2534         /* Verify */
2535         result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig);
2536         if (result != TSS_SUCCESS &&
2537             TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) {
2538                 stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s",
2539                     result, Trspi_Error_String(result));
2540         }
2541 
2542         if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) {
2543                 rc = CKR_SIGNATURE_INVALID;
2544         } else {
2545                 rc = CKR_OK;
2546         }
2547 
2548         return (rc);
2549 }
2550 
2551 CK_RV
2552 token_specific_rsa_sign(
2553         TSS_HCONTEXT hContext,
2554         CK_BYTE   * in_data,
2555         CK_ULONG    in_data_len,
2556         CK_BYTE   * out_data,
2557         CK_ULONG  * out_data_len,
2558         OBJECT    * key_obj)
2559 {
2560         TSS_RESULT      result;
2561         TSS_HHASH       hHash;
2562         BYTE            *sig;
2563         UINT32          sig_len;
2564         TSS_HKEY        hKey;
2565         CK_RV           rc;
2566 
2567         if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2568                 return (rc);
2569         }
2570 
2571         /* Create the hash object we'll use to sign */
2572         if ((result = Tspi_Context_CreateObject(hContext,
2573             TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) {
2574                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2575                     result, Trspi_Error_String(result));
2576                 return (CKR_FUNCTION_FAILED);
2577         }
2578 
2579         /* Insert the data into the hash object */
2580         if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len,
2581             in_data))) {
2582                 stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s",
2583                     result, Trspi_Error_String(result));
2584                 return (CKR_FUNCTION_FAILED);
2585         }
2586 
2587         /* Sign */
2588         if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) {
2589                 stlogit("Tspi_Hash_Sign: 0x%0x - %s",
2590                     result, Trspi_Error_String(result));
2591                 return (CKR_DATA_LEN_RANGE);
2592         }
2593 
2594         if (sig_len > *out_data_len) {
2595                 Tspi_Context_FreeMemory(hContext, sig);
2596                 return (CKR_BUFFER_TOO_SMALL);
2597         }
2598 
2599         (void) memcpy(out_data, sig, sig_len);
2600         *out_data_len = sig_len;
2601         Tspi_Context_FreeMemory(hContext, sig);
2602 
2603         return (CKR_OK);
2604 }
2605 
2606 CK_RV
2607 tpm_encrypt_data(
2608         TSS_HCONTEXT hContext,
2609         TSS_HKEY hKey,
2610         CK_BYTE *in_data,
2611         CK_ULONG in_data_len,
2612         CK_BYTE *out_data,
2613         CK_ULONG *out_data_len)
2614 {
2615         TSS_RESULT      result;
2616         TSS_HENCDATA    hEncData;
2617         BYTE            *dataBlob, *modulus;
2618         UINT32          dataBlobSize, modLen;
2619         CK_ULONG        chunklen, remain;
2620         CK_ULONG        outlen;
2621         UINT32          keyusage, scheme, maxsize;
2622 
2623         if ((result = Tspi_Context_CreateObject(hContext,
2624             TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) {
2625                 stlogit("Tspi_Context_CreateObject: 0x%0x - %s",
2626                     result, Trspi_Error_String(result));
2627                 return (CKR_FUNCTION_FAILED);
2628         }
2629         /*
2630          * Figure out the modulus size so we can break the data
2631          * into smaller chunks if necessary.
2632          */
2633         if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2634             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2635                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
2636                     result, Trspi_Error_String(result));
2637                 return (result);
2638         }
2639         /* we don't need the actual modulus */
2640         Tspi_Context_FreeMemory(hContext, modulus);
2641 
2642         /*
2643          * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5),
2644          * Max input data size varies depending on the key type and
2645          * encryption scheme.
2646          */
2647         if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2648             TSS_TSPATTRIB_KEYINFO_USAGE, &keyusage))) {
2649                 stlogit("Cannot find USAGE: %s\n",
2650                     Trspi_Error_String(result));
2651                 return (result);
2652         }
2653         if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2654             TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &scheme))) {
2655                 stlogit("Cannot find ENCSCHEME: %s\n",
2656                     Trspi_Error_String(result));
2657                 return (result);
2658         }
2659         switch (scheme) {
2660                 case TSS_ES_RSAESPKCSV15:
2661                         if (keyusage == TSS_KEYUSAGE_BIND)
2662                                 maxsize = 16;
2663                         else /* legacy */
2664                                 maxsize = 11;
2665                         break;
2666                 case TSS_ES_RSAESOAEP_SHA1_MGF1:
2667                         maxsize = 47;
2668                         break;
2669                 default:
2670                         maxsize = 0;
2671         }
2672 
2673         modLen -= maxsize;
2674 
2675         chunklen = (in_data_len > modLen ? modLen : in_data_len);
2676         remain = in_data_len;
2677         outlen = 0;
2678         while (remain > 0) {
2679                 if ((result = Tspi_Data_Bind(hEncData, hKey,
2680                     chunklen, in_data))) {
2681                         stlogit("Tspi_Data_Bind: 0x%0x - %s",
2682                             result, Trspi_Error_String(result));
2683                         return (CKR_FUNCTION_FAILED);
2684                 }
2685 
2686                 if ((result = Tspi_GetAttribData(hEncData,
2687                     TSS_TSPATTRIB_ENCDATA_BLOB,
2688                     TSS_TSPATTRIB_ENCDATABLOB_BLOB,
2689                     &dataBlobSize, &dataBlob))) {
2690                         stlogit("Tspi_GetAttribData: 0x%0x - %s",
2691                             result, Trspi_Error_String(result));
2692                         return (CKR_FUNCTION_FAILED);
2693                 }
2694 
2695                 if (outlen + dataBlobSize > *out_data_len) {
2696                         Tspi_Context_FreeMemory(hContext, dataBlob);
2697                         return (CKR_DATA_LEN_RANGE);
2698                 }
2699 
2700                 (void) memcpy(out_data + outlen,
2701                     dataBlob, dataBlobSize);
2702 
2703                 outlen += dataBlobSize;
2704                 in_data += chunklen;
2705                 remain -= chunklen;
2706 
2707                 if (chunklen > remain)
2708                         chunklen = remain;
2709 
2710                 Tspi_Context_FreeMemory(hContext, dataBlob);
2711         }
2712         *out_data_len = outlen;
2713 
2714         return (CKR_OK);
2715 }
2716 
2717 CK_RV
2718 token_specific_rsa_encrypt(
2719         TSS_HCONTEXT hContext,
2720         CK_BYTE   * in_data,
2721         CK_ULONG    in_data_len,
2722         CK_BYTE   * out_data,
2723         CK_ULONG  * out_data_len,
2724         OBJECT    * key_obj)
2725 {
2726         TSS_HKEY        hKey;
2727         CK_RV           rc;
2728 
2729         if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2730                 return (rc);
2731         }
2732 
2733         rc  = tpm_encrypt_data(hContext, hKey, in_data, in_data_len,
2734             out_data, out_data_len);
2735 
2736         return (rc);
2737 }
2738 
2739 /*
2740  * RSA Verify Recover
2741  *
2742  * Public key crypto is done in software, not by the TPM.
2743  * We bypass the TSPI library here in favor of calls directly
2744  * to OpenSSL because we don't want to add any padding, the in_data (signature)
2745  * already contains the data stream to be decrypted and is already
2746  * padded and formatted correctly.
2747  */
2748 CK_RV
2749 token_specific_rsa_verify_recover(
2750         TSS_HCONTEXT    hContext,
2751         CK_BYTE         *in_data,       /* signature */
2752         CK_ULONG        in_data_len,
2753         CK_BYTE         *out_data,      /* decrypted */
2754         CK_ULONG        *out_data_len,
2755         OBJECT          *key_obj)
2756 {
2757         TSS_HKEY        hKey;
2758         TSS_RESULT      result;
2759         CK_RV           rc;
2760         BYTE            *modulus;
2761         UINT32          modLen;
2762         RSA             *rsa = NULL;
2763         uchar_t         exp[] = { 0x01, 0x00, 0x01 };
2764         int             sslrv, num;
2765         BYTE            temp[MAX_RSA_KEYLENGTH];
2766         BYTE            outdata[MAX_RSA_KEYLENGTH];
2767         int             i;
2768 
2769         if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) {
2770                 return (rc);
2771         }
2772 
2773         if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO,
2774             TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) {
2775                 stlogit("Tspi_GetAttribData: 0x%0x - %s",
2776                     result, Trspi_Error_String(result));
2777                 return (CKR_FUNCTION_FAILED);
2778         }
2779 
2780         if (in_data_len != modLen) {
2781                 rc = CKR_SIGNATURE_LEN_RANGE;
2782                 goto end;
2783         }
2784 
2785         rsa = RSA_new();
2786         if (rsa == NULL) {
2787                 rc = CKR_HOST_MEMORY;
2788                 goto end;
2789         }
2790 
2791         rsa->n = BN_bin2bn(modulus, modLen, rsa->n);
2792         rsa->e = BN_bin2bn(exp, sizeof (exp), rsa->e);
2793         if (rsa->n == NULL || rsa->e == NULL) {
2794                 rc = CKR_HOST_MEMORY;
2795                 goto end;
2796         }
2797 
2798         rsa->flags |= RSA_FLAG_SIGN_VER;
2799 
2800         /* use RSA_NO_PADDING because the data is already padded (PKCS1) */
2801         sslrv = RSA_public_encrypt(in_data_len, in_data, outdata,
2802             rsa, RSA_NO_PADDING);
2803         if (sslrv == -1) {
2804                 rc = CKR_FUNCTION_FAILED;
2805                 goto end;
2806         }
2807 
2808         /* Strip leading 0's before stripping the padding */
2809         for (i = 0; i < sslrv; i++)
2810                 if (outdata[i] != 0)
2811                         break;
2812 
2813         num = BN_num_bytes(rsa->n);
2814 
2815         /* Use OpenSSL function for stripping PKCS#1 padding */
2816         sslrv = RSA_padding_check_PKCS1_type_1(temp, sizeof (temp),
2817             &outdata[i], sslrv - i, num);
2818 
2819         if (sslrv < 0) {
2820                 rc = CKR_FUNCTION_FAILED;
2821                 goto end;
2822         }
2823 
2824         if (*out_data_len < sslrv) {
2825                 rc = CKR_BUFFER_TOO_SMALL;
2826                 *out_data_len = 0;
2827                 goto end;
2828         }
2829 
2830         /* The return code indicates the number of bytes remaining */
2831         (void) memcpy(out_data, temp, sslrv);
2832         *out_data_len = sslrv;
2833 end:
2834         Tspi_Context_FreeMemory(hContext, modulus);
2835         if (rsa)
2836                 RSA_free(rsa);
2837 
2838         return (rc);
2839 }