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