147e946e7SWyllys Ingersoll /* 247e946e7SWyllys Ingersoll * The Initial Developer of the Original Code is International 347e946e7SWyllys Ingersoll * Business Machines Corporation. Portions created by IBM 447e946e7SWyllys Ingersoll * Corporation are Copyright (C) 2005 International Business 547e946e7SWyllys Ingersoll * Machines Corporation. All Rights Reserved. 647e946e7SWyllys Ingersoll * 747e946e7SWyllys Ingersoll * This program is free software; you can redistribute it and/or modify 847e946e7SWyllys Ingersoll * it under the terms of the Common Public License as published by 947e946e7SWyllys Ingersoll * IBM Corporation; either version 1 of the License, or (at your option) 1047e946e7SWyllys Ingersoll * any later version. 1147e946e7SWyllys Ingersoll * 1247e946e7SWyllys Ingersoll * This program is distributed in the hope that it will be useful, 1347e946e7SWyllys Ingersoll * but WITHOUT ANY WARRANTY; without even the implied warranty of 1447e946e7SWyllys Ingersoll * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1547e946e7SWyllys Ingersoll * Common Public License for more details. 1647e946e7SWyllys Ingersoll * 1747e946e7SWyllys Ingersoll * You should have received a copy of the Common Public License 1847e946e7SWyllys Ingersoll * along with this program; if not, a copy can be viewed at 1947e946e7SWyllys Ingersoll * http://www.opensource.org/licenses/cpl1.0.php. 2047e946e7SWyllys Ingersoll */ 2147e946e7SWyllys Ingersoll /* 2247e946e7SWyllys Ingersoll * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2347e946e7SWyllys Ingersoll * Use is subject to license terms. 2447e946e7SWyllys Ingersoll */ 2547e946e7SWyllys Ingersoll 2647e946e7SWyllys Ingersoll #include <pthread.h> 2747e946e7SWyllys Ingersoll #include <string.h> 2847e946e7SWyllys Ingersoll 2947e946e7SWyllys Ingersoll #include <sys/types.h> 3047e946e7SWyllys Ingersoll #include <sys/stat.h> 3147e946e7SWyllys Ingersoll #include <uuid/uuid.h> 3247e946e7SWyllys Ingersoll #include <fcntl.h> 3347e946e7SWyllys Ingersoll #include <errno.h> 3447e946e7SWyllys Ingersoll #include <pwd.h> 3547e946e7SWyllys Ingersoll #include <syslog.h> 3647e946e7SWyllys Ingersoll 37ab8176c2SWyllys Ingersoll #include <openssl/rsa.h> 38ab8176c2SWyllys Ingersoll 3947e946e7SWyllys Ingersoll #include <tss/platform.h> 4047e946e7SWyllys Ingersoll #include <tss/tss_defines.h> 4147e946e7SWyllys Ingersoll #include <tss/tss_typedef.h> 4247e946e7SWyllys Ingersoll #include <tss/tss_structs.h> 4347e946e7SWyllys Ingersoll #include <tss/tss_error.h> 4447e946e7SWyllys Ingersoll #include <tss/tcs_error.h> 4547e946e7SWyllys Ingersoll #include <tss/tspi.h> 4647e946e7SWyllys Ingersoll #include <trousers/trousers.h> 4747e946e7SWyllys Ingersoll 4847e946e7SWyllys Ingersoll #include "tpmtok_int.h" 4947e946e7SWyllys Ingersoll #include "tpmtok_defs.h" 5047e946e7SWyllys Ingersoll 51ab8176c2SWyllys Ingersoll #define MAX_RSA_KEYLENGTH 512 52ab8176c2SWyllys Ingersoll 5347e946e7SWyllys Ingersoll extern void stlogit(char *fmt, ...); 5447e946e7SWyllys Ingersoll 5547e946e7SWyllys Ingersoll CK_RV token_rng(TSS_HCONTEXT, CK_BYTE *, CK_ULONG); 5647e946e7SWyllys Ingersoll int tok_slot2local(CK_SLOT_ID); 5747e946e7SWyllys Ingersoll CK_RV token_specific_session(CK_SLOT_ID); 58ab8176c2SWyllys Ingersoll CK_RV token_specific_final(TSS_HCONTEXT); 5947e946e7SWyllys Ingersoll 6047e946e7SWyllys Ingersoll CK_RV 6147e946e7SWyllys Ingersoll token_specific_rsa_decrypt( 6247e946e7SWyllys Ingersoll TSS_HCONTEXT, 6347e946e7SWyllys Ingersoll CK_BYTE *, 6447e946e7SWyllys Ingersoll CK_ULONG, 6547e946e7SWyllys Ingersoll CK_BYTE *, 6647e946e7SWyllys Ingersoll CK_ULONG *, 6747e946e7SWyllys Ingersoll OBJECT *); 6847e946e7SWyllys Ingersoll 6947e946e7SWyllys Ingersoll CK_RV 7047e946e7SWyllys Ingersoll token_specific_rsa_encrypt( 7147e946e7SWyllys Ingersoll TSS_HCONTEXT, 7247e946e7SWyllys Ingersoll CK_BYTE *, 7347e946e7SWyllys Ingersoll CK_ULONG, 7447e946e7SWyllys Ingersoll CK_BYTE *, 7547e946e7SWyllys Ingersoll CK_ULONG *, 7647e946e7SWyllys Ingersoll OBJECT *); 7747e946e7SWyllys Ingersoll 7847e946e7SWyllys Ingersoll CK_RV 7947e946e7SWyllys Ingersoll token_specific_rsa_sign( 8047e946e7SWyllys Ingersoll TSS_HCONTEXT, 8147e946e7SWyllys Ingersoll CK_BYTE *, 8247e946e7SWyllys Ingersoll CK_ULONG, 8347e946e7SWyllys Ingersoll CK_BYTE *, 8447e946e7SWyllys Ingersoll CK_ULONG *, 8547e946e7SWyllys Ingersoll OBJECT *); 8647e946e7SWyllys Ingersoll 8747e946e7SWyllys Ingersoll CK_RV 8847e946e7SWyllys Ingersoll token_specific_rsa_verify(TSS_HCONTEXT, CK_BYTE *, 8947e946e7SWyllys Ingersoll CK_ULONG, CK_BYTE *, CK_ULONG, OBJECT *); 9047e946e7SWyllys Ingersoll 9147e946e7SWyllys Ingersoll CK_RV 9247e946e7SWyllys Ingersoll token_specific_rsa_generate_keypair(TSS_HCONTEXT, 9347e946e7SWyllys Ingersoll TEMPLATE *, 9447e946e7SWyllys Ingersoll TEMPLATE *); 9547e946e7SWyllys Ingersoll 9647e946e7SWyllys Ingersoll CK_RV 9747e946e7SWyllys Ingersoll token_specific_sha_init(DIGEST_CONTEXT *); 9847e946e7SWyllys Ingersoll 9947e946e7SWyllys Ingersoll CK_RV 10047e946e7SWyllys Ingersoll token_specific_sha_update(DIGEST_CONTEXT *, 10147e946e7SWyllys Ingersoll CK_BYTE *, 10247e946e7SWyllys Ingersoll CK_ULONG); 10347e946e7SWyllys Ingersoll 10447e946e7SWyllys Ingersoll CK_RV 10547e946e7SWyllys Ingersoll token_specific_sha_final(DIGEST_CONTEXT *, 10647e946e7SWyllys Ingersoll CK_BYTE *, 10747e946e7SWyllys Ingersoll CK_ULONG *); 10847e946e7SWyllys Ingersoll 10947e946e7SWyllys Ingersoll CK_RV token_specific_login(TSS_HCONTEXT, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG); 11047e946e7SWyllys Ingersoll CK_RV token_specific_logout(TSS_HCONTEXT); 11147e946e7SWyllys Ingersoll CK_RV token_specific_init_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG); 11247e946e7SWyllys Ingersoll CK_RV token_specific_set_pin(ST_SESSION_HANDLE, CK_CHAR_PTR, 11347e946e7SWyllys Ingersoll CK_ULONG, CK_CHAR_PTR, CK_ULONG); 11447e946e7SWyllys Ingersoll CK_RV token_specific_verify_so_pin(TSS_HCONTEXT, CK_CHAR_PTR, CK_ULONG); 11547e946e7SWyllys Ingersoll 11647e946e7SWyllys Ingersoll static CK_RV 11747e946e7SWyllys Ingersoll token_specific_init(char *, CK_SLOT_ID, TSS_HCONTEXT *); 11847e946e7SWyllys Ingersoll 11947e946e7SWyllys Ingersoll struct token_specific_struct token_specific = { 12047e946e7SWyllys Ingersoll "TPM_Debug", 12147e946e7SWyllys Ingersoll &token_specific_init, 12247e946e7SWyllys Ingersoll NULL, 12347e946e7SWyllys Ingersoll &token_rng, 12447e946e7SWyllys Ingersoll &token_specific_session, 12547e946e7SWyllys Ingersoll &token_specific_final, 12647e946e7SWyllys Ingersoll &token_specific_rsa_decrypt, 12747e946e7SWyllys Ingersoll &token_specific_rsa_encrypt, 12847e946e7SWyllys Ingersoll &token_specific_rsa_sign, 12947e946e7SWyllys Ingersoll &token_specific_rsa_verify, 13047e946e7SWyllys Ingersoll &token_specific_rsa_generate_keypair, 13147e946e7SWyllys Ingersoll NULL, 13247e946e7SWyllys Ingersoll NULL, 13347e946e7SWyllys Ingersoll NULL, 13447e946e7SWyllys Ingersoll &token_specific_login, 13547e946e7SWyllys Ingersoll &token_specific_logout, 13647e946e7SWyllys Ingersoll &token_specific_init_pin, 13747e946e7SWyllys Ingersoll &token_specific_set_pin, 13847e946e7SWyllys Ingersoll &token_specific_verify_so_pin 13947e946e7SWyllys Ingersoll }; 14047e946e7SWyllys Ingersoll 14147e946e7SWyllys Ingersoll /* The context we'll use globally to connect to the TSP */ 14247e946e7SWyllys Ingersoll 14347e946e7SWyllys Ingersoll /* TSP key handles */ 14447e946e7SWyllys Ingersoll TSS_HKEY hPublicRootKey = NULL_HKEY; 14547e946e7SWyllys Ingersoll TSS_HKEY hPublicLeafKey = NULL_HKEY; 14647e946e7SWyllys Ingersoll TSS_HKEY hPrivateRootKey = NULL_HKEY; 14747e946e7SWyllys Ingersoll TSS_HKEY hPrivateLeafKey = NULL_HKEY; 14847e946e7SWyllys Ingersoll 14947e946e7SWyllys Ingersoll TSS_UUID publicRootKeyUUID; 15047e946e7SWyllys Ingersoll TSS_UUID publicLeafKeyUUID; 15147e946e7SWyllys Ingersoll TSS_UUID privateRootKeyUUID; 15247e946e7SWyllys Ingersoll TSS_UUID privateLeafKeyUUID; 15347e946e7SWyllys Ingersoll 15447e946e7SWyllys Ingersoll /* TSP policy handles */ 15547e946e7SWyllys Ingersoll TSS_HPOLICY hDefaultPolicy = NULL_HPOLICY; 15647e946e7SWyllys Ingersoll 15747e946e7SWyllys Ingersoll /* PKCS#11 key handles */ 15847e946e7SWyllys Ingersoll int not_initialized = 0; 15947e946e7SWyllys Ingersoll 16047e946e7SWyllys Ingersoll CK_BYTE current_user_pin_sha[SHA1_DIGEST_LENGTH]; 16147e946e7SWyllys Ingersoll CK_BYTE current_so_pin_sha[SHA1_DIGEST_LENGTH]; 16247e946e7SWyllys Ingersoll 16347e946e7SWyllys Ingersoll static TPM_CAP_VERSION_INFO tpmvinfo; 16447e946e7SWyllys Ingersoll 16547e946e7SWyllys Ingersoll static CK_RV 16647e946e7SWyllys Ingersoll verify_user_pin(TSS_HCONTEXT, CK_BYTE *); 16747e946e7SWyllys Ingersoll 168ab8176c2SWyllys Ingersoll static TSS_RESULT 169ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *); 170ab8176c2SWyllys Ingersoll 171ab8176c2SWyllys Ingersoll static TSS_RESULT 172ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY); 173ab8176c2SWyllys Ingersoll 17447e946e7SWyllys Ingersoll static void 17547e946e7SWyllys Ingersoll local_uuid_clear(TSS_UUID *uuid) 17647e946e7SWyllys Ingersoll { 17747e946e7SWyllys Ingersoll if (uuid == NULL) 17847e946e7SWyllys Ingersoll return; 17947e946e7SWyllys Ingersoll (void) memset(uuid, 0, sizeof (TSS_UUID)); 18047e946e7SWyllys Ingersoll } 18147e946e7SWyllys Ingersoll 18247e946e7SWyllys Ingersoll 18347e946e7SWyllys Ingersoll /* convert from TSS_UUID to uuid_t */ 18447e946e7SWyllys Ingersoll static void 18547e946e7SWyllys Ingersoll tss_uuid_convert_from(TSS_UUID *uu, uuid_t ptr) 18647e946e7SWyllys Ingersoll { 18747e946e7SWyllys Ingersoll uint_t tmp; 18847e946e7SWyllys Ingersoll uchar_t *out = ptr; 18947e946e7SWyllys Ingersoll 19047e946e7SWyllys Ingersoll tmp = ntohl(uu->ulTimeLow); 19147e946e7SWyllys Ingersoll out[3] = (uchar_t)tmp; 19247e946e7SWyllys Ingersoll tmp >>= 8; 19347e946e7SWyllys Ingersoll out[2] = (uchar_t)tmp; 19447e946e7SWyllys Ingersoll tmp >>= 8; 19547e946e7SWyllys Ingersoll out[1] = (uchar_t)tmp; 19647e946e7SWyllys Ingersoll tmp >>= 8; 19747e946e7SWyllys Ingersoll out[0] = (uchar_t)tmp; 19847e946e7SWyllys Ingersoll 19947e946e7SWyllys Ingersoll tmp = ntohs(uu->usTimeMid); 20047e946e7SWyllys Ingersoll out[5] = (uchar_t)tmp; 20147e946e7SWyllys Ingersoll tmp >>= 8; 20247e946e7SWyllys Ingersoll out[4] = (uchar_t)tmp; 20347e946e7SWyllys Ingersoll 20447e946e7SWyllys Ingersoll tmp = ntohs(uu->usTimeHigh); 20547e946e7SWyllys Ingersoll out[7] = (uchar_t)tmp; 20647e946e7SWyllys Ingersoll tmp >>= 8; 20747e946e7SWyllys Ingersoll out[6] = (uchar_t)tmp; 20847e946e7SWyllys Ingersoll 20947e946e7SWyllys Ingersoll tmp = uu->bClockSeqHigh; 21047e946e7SWyllys Ingersoll out[8] = (uchar_t)tmp; 21147e946e7SWyllys Ingersoll tmp = uu->bClockSeqLow; 21247e946e7SWyllys Ingersoll out[9] = (uchar_t)tmp; 21347e946e7SWyllys Ingersoll 21447e946e7SWyllys Ingersoll (void) memcpy(out+10, uu->rgbNode, 6); 21547e946e7SWyllys Ingersoll } 21647e946e7SWyllys Ingersoll 21747e946e7SWyllys Ingersoll /* convert from uuid_t to TSS_UUID */ 21847e946e7SWyllys Ingersoll static void 21947e946e7SWyllys Ingersoll tss_uuid_convert_to(TSS_UUID *uuid, uuid_t in) 22047e946e7SWyllys Ingersoll { 22147e946e7SWyllys Ingersoll uchar_t *ptr; 22247e946e7SWyllys Ingersoll uint32_t ltmp; 22347e946e7SWyllys Ingersoll uint16_t stmp; 22447e946e7SWyllys Ingersoll 22547e946e7SWyllys Ingersoll ptr = in; 22647e946e7SWyllys Ingersoll 22747e946e7SWyllys Ingersoll ltmp = *ptr++; 22847e946e7SWyllys Ingersoll ltmp = (ltmp << 8) | *ptr++; 22947e946e7SWyllys Ingersoll ltmp = (ltmp << 8) | *ptr++; 23047e946e7SWyllys Ingersoll ltmp = (ltmp << 8) | *ptr++; 23147e946e7SWyllys Ingersoll uuid->ulTimeLow = ntohl(ltmp); 23247e946e7SWyllys Ingersoll 23347e946e7SWyllys Ingersoll stmp = *ptr++; 23447e946e7SWyllys Ingersoll stmp = (stmp << 8) | *ptr++; 23547e946e7SWyllys Ingersoll uuid->usTimeMid = ntohs(stmp); 23647e946e7SWyllys Ingersoll 23747e946e7SWyllys Ingersoll stmp = *ptr++; 23847e946e7SWyllys Ingersoll stmp = (stmp << 8) | *ptr++; 23947e946e7SWyllys Ingersoll uuid->usTimeHigh = ntohs(stmp); 24047e946e7SWyllys Ingersoll 24147e946e7SWyllys Ingersoll uuid->bClockSeqHigh = *ptr++; 24247e946e7SWyllys Ingersoll 24347e946e7SWyllys Ingersoll uuid->bClockSeqLow = *ptr++; 24447e946e7SWyllys Ingersoll 24547e946e7SWyllys Ingersoll (void) memcpy(uuid->rgbNode, ptr, 6); 24647e946e7SWyllys Ingersoll } 24747e946e7SWyllys Ingersoll 24847e946e7SWyllys Ingersoll static void 24947e946e7SWyllys Ingersoll local_uuid_copy(TSS_UUID *dst, TSS_UUID *src) 25047e946e7SWyllys Ingersoll { 25147e946e7SWyllys Ingersoll uuid_t udst, usrc; 25247e946e7SWyllys Ingersoll 25347e946e7SWyllys Ingersoll tss_uuid_convert_from(dst, udst); 25447e946e7SWyllys Ingersoll tss_uuid_convert_from(src, usrc); 25547e946e7SWyllys Ingersoll 25647e946e7SWyllys Ingersoll uuid_copy(udst, usrc); 25747e946e7SWyllys Ingersoll 25847e946e7SWyllys Ingersoll tss_uuid_convert_to(dst, udst); 25947e946e7SWyllys Ingersoll } 26047e946e7SWyllys Ingersoll 26147e946e7SWyllys Ingersoll static void 26247e946e7SWyllys Ingersoll local_uuid_generate(TSS_UUID *uu) 26347e946e7SWyllys Ingersoll { 26447e946e7SWyllys Ingersoll uuid_t newuuid; 26547e946e7SWyllys Ingersoll 26647e946e7SWyllys Ingersoll uuid_generate(newuuid); 26747e946e7SWyllys Ingersoll 26847e946e7SWyllys Ingersoll tss_uuid_convert_to(uu, newuuid); 26947e946e7SWyllys Ingersoll } 27047e946e7SWyllys Ingersoll 27147e946e7SWyllys Ingersoll static int 27247e946e7SWyllys Ingersoll local_copy_file(char *dst, char *src) 27347e946e7SWyllys Ingersoll { 27447e946e7SWyllys Ingersoll FILE *fdest, *fsrc; 27547e946e7SWyllys Ingersoll char line[BUFSIZ]; 27647e946e7SWyllys Ingersoll 27747e946e7SWyllys Ingersoll fdest = fopen(dst, "w"); 27847e946e7SWyllys Ingersoll if (fdest == NULL) 27947e946e7SWyllys Ingersoll return (-1); 28047e946e7SWyllys Ingersoll 28147e946e7SWyllys Ingersoll fsrc = fopen(src, "r"); 28247e946e7SWyllys Ingersoll if (fsrc == NULL) { 28347e946e7SWyllys Ingersoll (void) fclose(fdest); 28447e946e7SWyllys Ingersoll return (-1); 28547e946e7SWyllys Ingersoll } 28647e946e7SWyllys Ingersoll 28747e946e7SWyllys Ingersoll while (fread(line, sizeof (line), 1, fsrc)) 28847e946e7SWyllys Ingersoll (void) fprintf(fdest, "%s\n", line); 28947e946e7SWyllys Ingersoll (void) fclose(fsrc); 29047e946e7SWyllys Ingersoll (void) fclose(fdest); 29147e946e7SWyllys Ingersoll return (0); 29247e946e7SWyllys Ingersoll } 29347e946e7SWyllys Ingersoll 29447e946e7SWyllys Ingersoll static int 29547e946e7SWyllys Ingersoll remove_uuid(char *keyname) 29647e946e7SWyllys Ingersoll { 29747e946e7SWyllys Ingersoll int ret = 0; 29847e946e7SWyllys Ingersoll FILE *fp, *newfp; 29947e946e7SWyllys Ingersoll char fname[MAXPATHLEN]; 30047e946e7SWyllys Ingersoll char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ]; 30147e946e7SWyllys Ingersoll char *tmpfname; 30247e946e7SWyllys Ingersoll char *p = get_tpm_keystore_path(); 30347e946e7SWyllys Ingersoll 30447e946e7SWyllys Ingersoll if (p == NULL) 30547e946e7SWyllys Ingersoll return (-1); 30647e946e7SWyllys Ingersoll 30747e946e7SWyllys Ingersoll (void) snprintf(fname, sizeof (fname), 30847e946e7SWyllys Ingersoll "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); 30947e946e7SWyllys Ingersoll 31047e946e7SWyllys Ingersoll fp = fopen(fname, "r"); 31147e946e7SWyllys Ingersoll if (fp == NULL) { 31247e946e7SWyllys Ingersoll return (-1); 31347e946e7SWyllys Ingersoll } 31447e946e7SWyllys Ingersoll 31547e946e7SWyllys Ingersoll tmpfname = tempnam("/tmp", "tpmtok"); 31647e946e7SWyllys Ingersoll newfp = fopen(tmpfname, "w+"); 31747e946e7SWyllys Ingersoll if (newfp == NULL) { 31847e946e7SWyllys Ingersoll free(tmpfname); 31947e946e7SWyllys Ingersoll (void) fclose(fp); 32047e946e7SWyllys Ingersoll return (-1); 32147e946e7SWyllys Ingersoll } 32247e946e7SWyllys Ingersoll 32347e946e7SWyllys Ingersoll while (!feof(fp)) { 32447e946e7SWyllys Ingersoll (void) fgets(line, sizeof (line), fp); 32547e946e7SWyllys Ingersoll if (sscanf(line, "%1024s %1024s", key, idstr) == 2) { 32647e946e7SWyllys Ingersoll if (strcmp(key, keyname)) 32747e946e7SWyllys Ingersoll (void) fprintf(newfp, "%s\n", line); 32847e946e7SWyllys Ingersoll } 32947e946e7SWyllys Ingersoll } 33047e946e7SWyllys Ingersoll 33147e946e7SWyllys Ingersoll (void) fclose(fp); 33247e946e7SWyllys Ingersoll (void) fclose(newfp); 33347e946e7SWyllys Ingersoll if (local_copy_file(fname, tmpfname) == 0) 33447e946e7SWyllys Ingersoll (void) unlink(tmpfname); 33547e946e7SWyllys Ingersoll 33647e946e7SWyllys Ingersoll free(tmpfname); 33747e946e7SWyllys Ingersoll 33847e946e7SWyllys Ingersoll return (ret); 33947e946e7SWyllys Ingersoll } 34047e946e7SWyllys Ingersoll 34147e946e7SWyllys Ingersoll static int 34247e946e7SWyllys Ingersoll find_uuid(char *keyname, TSS_UUID *uu) 34347e946e7SWyllys Ingersoll { 34447e946e7SWyllys Ingersoll int ret = 0, found = 0; 34547e946e7SWyllys Ingersoll FILE *fp = NULL; 34647e946e7SWyllys Ingersoll char fname[MAXPATHLEN]; 34747e946e7SWyllys Ingersoll char line[BUFSIZ], key[BUFSIZ], idstr[BUFSIZ]; 34847e946e7SWyllys Ingersoll uuid_t uuid; 34947e946e7SWyllys Ingersoll char *p = get_tpm_keystore_path(); 35047e946e7SWyllys Ingersoll 35147e946e7SWyllys Ingersoll if (p == NULL) 35247e946e7SWyllys Ingersoll return (-1); 35347e946e7SWyllys Ingersoll 35447e946e7SWyllys Ingersoll tss_uuid_convert_from(uu, uuid); 35547e946e7SWyllys Ingersoll 35647e946e7SWyllys Ingersoll (void) snprintf(fname, sizeof (fname), 35747e946e7SWyllys Ingersoll "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); 35847e946e7SWyllys Ingersoll 35947e946e7SWyllys Ingersoll /* Open UUID Index file */ 36047e946e7SWyllys Ingersoll fp = fopen(fname, "r"); 36147e946e7SWyllys Ingersoll if (fp == NULL) { 36247e946e7SWyllys Ingersoll if (errno == ENOENT) { 36347e946e7SWyllys Ingersoll /* initialize the file */ 36447e946e7SWyllys Ingersoll fp = fopen(fname, "w"); 36547e946e7SWyllys Ingersoll if (fp != NULL) 36647e946e7SWyllys Ingersoll (void) fclose(fp); 36747e946e7SWyllys Ingersoll } 36847e946e7SWyllys Ingersoll return (-1); 36947e946e7SWyllys Ingersoll } 37047e946e7SWyllys Ingersoll 37147e946e7SWyllys Ingersoll while (!feof(fp)) { 37247e946e7SWyllys Ingersoll (void) fgets(line, sizeof (line), fp); 37347e946e7SWyllys Ingersoll if (sscanf(line, "%1024s %1024s", key, idstr) == 2) { 37447e946e7SWyllys Ingersoll if (strcmp(key, keyname) == 0) { 37547e946e7SWyllys Ingersoll ret = uuid_parse(idstr, uuid); 37647e946e7SWyllys Ingersoll if (ret == 0) { 37747e946e7SWyllys Ingersoll found = 1; 37847e946e7SWyllys Ingersoll tss_uuid_convert_to(uu, 37947e946e7SWyllys Ingersoll uuid); 38047e946e7SWyllys Ingersoll } 38147e946e7SWyllys Ingersoll break; 38247e946e7SWyllys Ingersoll } 38347e946e7SWyllys Ingersoll } 38447e946e7SWyllys Ingersoll } 38547e946e7SWyllys Ingersoll (void) fclose(fp); 38647e946e7SWyllys Ingersoll 38747e946e7SWyllys Ingersoll if (!found) 38847e946e7SWyllys Ingersoll ret = -1; 38947e946e7SWyllys Ingersoll return (ret); 39047e946e7SWyllys Ingersoll } 39147e946e7SWyllys Ingersoll 39247e946e7SWyllys Ingersoll static int 39347e946e7SWyllys Ingersoll local_uuid_is_null(TSS_UUID *uu) 39447e946e7SWyllys Ingersoll { 39547e946e7SWyllys Ingersoll uuid_t uuid; 39647e946e7SWyllys Ingersoll int nulluuid; 39747e946e7SWyllys Ingersoll 39847e946e7SWyllys Ingersoll tss_uuid_convert_from(uu, uuid); 39947e946e7SWyllys Ingersoll 40047e946e7SWyllys Ingersoll nulluuid = uuid_is_null(uuid); 40147e946e7SWyllys Ingersoll return (nulluuid); 40247e946e7SWyllys Ingersoll } 40347e946e7SWyllys Ingersoll 40447e946e7SWyllys Ingersoll static int 40547e946e7SWyllys Ingersoll add_uuid(char *keyname, TSS_UUID *uu) 40647e946e7SWyllys Ingersoll { 40747e946e7SWyllys Ingersoll FILE *fp = NULL; 40847e946e7SWyllys Ingersoll char fname[MAXPATHLEN]; 40947e946e7SWyllys Ingersoll char idstr[BUFSIZ]; 41047e946e7SWyllys Ingersoll uuid_t uuid; 41147e946e7SWyllys Ingersoll char *p = get_tpm_keystore_path(); 41247e946e7SWyllys Ingersoll 41347e946e7SWyllys Ingersoll if (p == NULL) 41447e946e7SWyllys Ingersoll return (-1); 41547e946e7SWyllys Ingersoll 41647e946e7SWyllys Ingersoll tss_uuid_convert_from(uu, uuid); 41747e946e7SWyllys Ingersoll 41847e946e7SWyllys Ingersoll if (uuid_is_null(uuid)) 41947e946e7SWyllys Ingersoll return (-1); 42047e946e7SWyllys Ingersoll 42147e946e7SWyllys Ingersoll uuid_unparse(uuid, idstr); 42247e946e7SWyllys Ingersoll 42347e946e7SWyllys Ingersoll (void) snprintf(fname, sizeof (fname), 42447e946e7SWyllys Ingersoll "%s/%s", p, TPMTOK_UUID_INDEX_FILENAME); 42547e946e7SWyllys Ingersoll 42647e946e7SWyllys Ingersoll fp = fopen(fname, "a"); 42747e946e7SWyllys Ingersoll if (fp == NULL) 42847e946e7SWyllys Ingersoll return (-1); 42947e946e7SWyllys Ingersoll 43047e946e7SWyllys Ingersoll (void) fprintf(fp, "%s %s\n", keyname, idstr); 43147e946e7SWyllys Ingersoll (void) fclose(fp); 43247e946e7SWyllys Ingersoll 43347e946e7SWyllys Ingersoll return (0); 43447e946e7SWyllys Ingersoll } 43547e946e7SWyllys Ingersoll 43647e946e7SWyllys Ingersoll 43747e946e7SWyllys Ingersoll static UINT32 43847e946e7SWyllys Ingersoll util_get_keysize_flag(CK_ULONG size) 43947e946e7SWyllys Ingersoll { 44047e946e7SWyllys Ingersoll switch (size) { 44147e946e7SWyllys Ingersoll case 512: 44247e946e7SWyllys Ingersoll return (TSS_KEY_SIZE_512); 44347e946e7SWyllys Ingersoll break; 44447e946e7SWyllys Ingersoll case 1024: 44547e946e7SWyllys Ingersoll return (TSS_KEY_SIZE_1024); 44647e946e7SWyllys Ingersoll break; 44747e946e7SWyllys Ingersoll case 2048: 44847e946e7SWyllys Ingersoll return (TSS_KEY_SIZE_2048); 44947e946e7SWyllys Ingersoll break; 45047e946e7SWyllys Ingersoll default: 45147e946e7SWyllys Ingersoll break; 45247e946e7SWyllys Ingersoll } 45347e946e7SWyllys Ingersoll 45447e946e7SWyllys Ingersoll return (0); 45547e946e7SWyllys Ingersoll } 45647e946e7SWyllys Ingersoll 45747e946e7SWyllys Ingersoll /* make sure the public exponent attribute is 65537 */ 45847e946e7SWyllys Ingersoll static CK_ULONG 45947e946e7SWyllys Ingersoll util_check_public_exponent(TEMPLATE *tmpl) 46047e946e7SWyllys Ingersoll { 46147e946e7SWyllys Ingersoll CK_BBOOL flag; 46247e946e7SWyllys Ingersoll CK_ATTRIBUTE *publ_exp_attr; 46347e946e7SWyllys Ingersoll CK_BYTE pubexp_bytes[] = { 1, 0, 1 }; 46447e946e7SWyllys Ingersoll CK_ULONG publ_exp, rc = 1; 46547e946e7SWyllys Ingersoll 46647e946e7SWyllys Ingersoll flag = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, 46747e946e7SWyllys Ingersoll &publ_exp_attr); 46847e946e7SWyllys Ingersoll if (!flag) { 46947e946e7SWyllys Ingersoll LogError1("Couldn't find public exponent attribute"); 47047e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 47147e946e7SWyllys Ingersoll } 47247e946e7SWyllys Ingersoll 47347e946e7SWyllys Ingersoll switch (publ_exp_attr->ulValueLen) { 47447e946e7SWyllys Ingersoll case 3: 47547e946e7SWyllys Ingersoll rc = memcmp(pubexp_bytes, publ_exp_attr->pValue, 3); 47647e946e7SWyllys Ingersoll break; 47747e946e7SWyllys Ingersoll case sizeof (CK_ULONG): 47847e946e7SWyllys Ingersoll publ_exp = *((CK_ULONG *)publ_exp_attr->pValue); 47947e946e7SWyllys Ingersoll if (publ_exp == 65537) 48047e946e7SWyllys Ingersoll rc = 0; 48147e946e7SWyllys Ingersoll break; 48247e946e7SWyllys Ingersoll default: 48347e946e7SWyllys Ingersoll break; 48447e946e7SWyllys Ingersoll } 48547e946e7SWyllys Ingersoll 48647e946e7SWyllys Ingersoll return (rc); 48747e946e7SWyllys Ingersoll } 48847e946e7SWyllys Ingersoll 48947e946e7SWyllys Ingersoll TSS_RESULT 49047e946e7SWyllys Ingersoll set_public_modulus(TSS_HCONTEXT hContext, TSS_HKEY hKey, 49147e946e7SWyllys Ingersoll unsigned long size_n, unsigned char *n) 49247e946e7SWyllys Ingersoll { 49347e946e7SWyllys Ingersoll UINT64 offset; 49447e946e7SWyllys Ingersoll UINT32 blob_size; 49547e946e7SWyllys Ingersoll BYTE *blob, pub_blob[1024]; 49647e946e7SWyllys Ingersoll TCPA_PUBKEY pub_key; 49747e946e7SWyllys Ingersoll TSS_RESULT result; 49847e946e7SWyllys Ingersoll 49947e946e7SWyllys Ingersoll /* Get the TCPA_PUBKEY blob from the key object. */ 50047e946e7SWyllys Ingersoll result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, 50147e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &blob_size, &blob); 50247e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 50347e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData failed: rc=0x%0x - %s\n", 50447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 50547e946e7SWyllys Ingersoll return (result); 50647e946e7SWyllys Ingersoll } 50747e946e7SWyllys Ingersoll 50847e946e7SWyllys Ingersoll offset = 0; 50947e946e7SWyllys Ingersoll result = Trspi_UnloadBlob_PUBKEY(&offset, blob, &pub_key); 51047e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 51147e946e7SWyllys Ingersoll stlogit("Trspi_UnloadBlob_PUBKEY failed: rc=0x%0x - %s\n", 51247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 51347e946e7SWyllys Ingersoll return (result); 51447e946e7SWyllys Ingersoll } 51547e946e7SWyllys Ingersoll 51647e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, blob); 51747e946e7SWyllys Ingersoll /* Free the first dangling reference, putting 'n' in its place */ 51847e946e7SWyllys Ingersoll free(pub_key.pubKey.key); 51947e946e7SWyllys Ingersoll pub_key.pubKey.keyLength = size_n; 52047e946e7SWyllys Ingersoll pub_key.pubKey.key = n; 52147e946e7SWyllys Ingersoll 52247e946e7SWyllys Ingersoll offset = 0; 52347e946e7SWyllys Ingersoll Trspi_LoadBlob_PUBKEY(&offset, pub_blob, &pub_key); 52447e946e7SWyllys Ingersoll 52547e946e7SWyllys Ingersoll /* Free the second dangling reference */ 52647e946e7SWyllys Ingersoll free(pub_key.algorithmParms.parms); 52747e946e7SWyllys Ingersoll 52847e946e7SWyllys Ingersoll /* set the public key data in the TSS object */ 52947e946e7SWyllys Ingersoll result = Tspi_SetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, 53047e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, (UINT32)offset, pub_blob); 53147e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 53247e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData failed: rc=0x%0x - %s\n", 53347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 53447e946e7SWyllys Ingersoll return (result); 53547e946e7SWyllys Ingersoll } 53647e946e7SWyllys Ingersoll 53747e946e7SWyllys Ingersoll return (result); 53847e946e7SWyllys Ingersoll } 53947e946e7SWyllys Ingersoll 54047e946e7SWyllys Ingersoll /* 54147e946e7SWyllys Ingersoll * Get details about the TPM to put into the token_info structure. 54247e946e7SWyllys Ingersoll */ 54347e946e7SWyllys Ingersoll CK_RV 54447e946e7SWyllys Ingersoll token_get_tpm_info(TSS_HCONTEXT hContext, TOKEN_DATA *td) 54547e946e7SWyllys Ingersoll { 54647e946e7SWyllys Ingersoll TSS_RESULT result; 54747e946e7SWyllys Ingersoll TPM_CAPABILITY_AREA capArea = TSS_TPMCAP_VERSION_VAL; 54847e946e7SWyllys Ingersoll UINT32 datalen; 54947e946e7SWyllys Ingersoll BYTE *data; 55047e946e7SWyllys Ingersoll TSS_HTPM hTPM; 55147e946e7SWyllys Ingersoll 55247e946e7SWyllys Ingersoll if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) { 55347e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", 55447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 55547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 55647e946e7SWyllys Ingersoll } 55747e946e7SWyllys Ingersoll if ((result = Tspi_TPM_GetCapability(hTPM, 55847e946e7SWyllys Ingersoll capArea, 0, NULL, &datalen, &data)) != 0 || datalen == 0 || 55947e946e7SWyllys Ingersoll data == NULL) { 56047e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetCapability: 0x%0x - %s", 56147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 56247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 56347e946e7SWyllys Ingersoll } 56447e946e7SWyllys Ingersoll if (datalen > sizeof (tpmvinfo)) { 56547e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, data); 56647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 56747e946e7SWyllys Ingersoll } 56847e946e7SWyllys Ingersoll 569*1dc1cb45SWyllys Ingersoll (void) memcpy(&tpmvinfo, (void *)data, datalen); 57047e946e7SWyllys Ingersoll 57147e946e7SWyllys Ingersoll bzero(td->token_info.manufacturerID, 57247e946e7SWyllys Ingersoll sizeof (td->token_info.manufacturerID)); 57347e946e7SWyllys Ingersoll 57447e946e7SWyllys Ingersoll (void) memset(td->token_info.manufacturerID, ' ', 57547e946e7SWyllys Ingersoll sizeof (td->token_info.manufacturerID) - 1); 576*1dc1cb45SWyllys Ingersoll 57747e946e7SWyllys Ingersoll (void) memcpy(td->token_info.manufacturerID, 57847e946e7SWyllys Ingersoll tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID)); 57947e946e7SWyllys Ingersoll 58047e946e7SWyllys Ingersoll (void) memset(td->token_info.label, ' ', 58147e946e7SWyllys Ingersoll sizeof (td->token_info.label) - 1); 582*1dc1cb45SWyllys Ingersoll 583*1dc1cb45SWyllys Ingersoll (void) memcpy(td->token_info.label, "TPM", 3); 58447e946e7SWyllys Ingersoll 58547e946e7SWyllys Ingersoll td->token_info.hardwareVersion.major = tpmvinfo.version.major; 58647e946e7SWyllys Ingersoll td->token_info.hardwareVersion.minor = tpmvinfo.version.minor; 58747e946e7SWyllys Ingersoll td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor; 58847e946e7SWyllys Ingersoll td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor; 58947e946e7SWyllys Ingersoll 59047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, data); 59147e946e7SWyllys Ingersoll return (CKR_OK); 59247e946e7SWyllys Ingersoll } 59347e946e7SWyllys Ingersoll 59447e946e7SWyllys Ingersoll /*ARGSUSED*/ 59547e946e7SWyllys Ingersoll CK_RV 59647e946e7SWyllys Ingersoll token_specific_session(CK_SLOT_ID slotid) 59747e946e7SWyllys Ingersoll { 59847e946e7SWyllys Ingersoll return (CKR_OK); 59947e946e7SWyllys Ingersoll } 60047e946e7SWyllys Ingersoll 60147e946e7SWyllys Ingersoll CK_RV 60247e946e7SWyllys Ingersoll token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes) 60347e946e7SWyllys Ingersoll { 60447e946e7SWyllys Ingersoll TSS_RESULT rc; 60547e946e7SWyllys Ingersoll TSS_HTPM hTPM; 60647e946e7SWyllys Ingersoll BYTE *random_bytes = NULL; 60747e946e7SWyllys Ingersoll 60847e946e7SWyllys Ingersoll if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) { 60947e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", 61047e946e7SWyllys Ingersoll rc, Trspi_Error_String(rc)); 61147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 61247e946e7SWyllys Ingersoll } 61347e946e7SWyllys Ingersoll 61447e946e7SWyllys Ingersoll if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) { 61547e946e7SWyllys Ingersoll stlogit("Tspi_TPM_GetRandom: 0x%0x - %s", 61647e946e7SWyllys Ingersoll rc, Trspi_Error_String(rc)); 61747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 61847e946e7SWyllys Ingersoll } 61947e946e7SWyllys Ingersoll 62047e946e7SWyllys Ingersoll (void) memcpy(output, random_bytes, bytes); 62147e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, random_bytes); 62247e946e7SWyllys Ingersoll 62347e946e7SWyllys Ingersoll return (CKR_OK); 62447e946e7SWyllys Ingersoll } 62547e946e7SWyllys Ingersoll 62647e946e7SWyllys Ingersoll TSS_RESULT 62747e946e7SWyllys Ingersoll open_tss_context(TSS_HCONTEXT *pContext) 62847e946e7SWyllys Ingersoll { 62947e946e7SWyllys Ingersoll TSS_RESULT result; 63047e946e7SWyllys Ingersoll 63147e946e7SWyllys Ingersoll if ((result = Tspi_Context_Create(pContext))) { 63247e946e7SWyllys Ingersoll stlogit("Tspi_Context_Create: 0x%0x - %s", 63347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 63447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 63547e946e7SWyllys Ingersoll } 63647e946e7SWyllys Ingersoll 63747e946e7SWyllys Ingersoll if ((result = Tspi_Context_Connect(*pContext, NULL))) { 63847e946e7SWyllys Ingersoll stlogit("Tspi_Context_Connect: 0x%0x - %s", 63947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 64047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 64147e946e7SWyllys Ingersoll } 64247e946e7SWyllys Ingersoll return (result); 64347e946e7SWyllys Ingersoll } 64447e946e7SWyllys Ingersoll 64547e946e7SWyllys Ingersoll /*ARGSUSED*/ 64647e946e7SWyllys Ingersoll static CK_RV 64747e946e7SWyllys Ingersoll token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber, 64847e946e7SWyllys Ingersoll TSS_HCONTEXT *hContext) 64947e946e7SWyllys Ingersoll { 65047e946e7SWyllys Ingersoll TSS_RESULT result; 65147e946e7SWyllys Ingersoll 65247e946e7SWyllys Ingersoll result = open_tss_context(hContext); 65347e946e7SWyllys Ingersoll if (result) 65447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 65547e946e7SWyllys Ingersoll 65647e946e7SWyllys Ingersoll if ((result = Tspi_Context_GetDefaultPolicy(*hContext, 65747e946e7SWyllys Ingersoll &hDefaultPolicy))) { 65847e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s", 65947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 66047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 66147e946e7SWyllys Ingersoll } 66247e946e7SWyllys Ingersoll 66347e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 66447e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 66547e946e7SWyllys Ingersoll local_uuid_clear(&publicLeafKeyUUID); 66647e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 66747e946e7SWyllys Ingersoll 66847e946e7SWyllys Ingersoll result = token_get_tpm_info(*hContext, nv_token_data); 66947e946e7SWyllys Ingersoll return (result); 67047e946e7SWyllys Ingersoll } 67147e946e7SWyllys Ingersoll 67247e946e7SWyllys Ingersoll /* 67347e946e7SWyllys Ingersoll * Given a modulus and prime from an RSA key, create a TSS_HKEY object by 67447e946e7SWyllys Ingersoll * wrapping the RSA key with a key from the TPM (SRK or other previously stored 67547e946e7SWyllys Ingersoll * key). 67647e946e7SWyllys Ingersoll */ 67747e946e7SWyllys Ingersoll static CK_RV 67847e946e7SWyllys Ingersoll token_wrap_sw_key( 67947e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 68047e946e7SWyllys Ingersoll int size_n, 68147e946e7SWyllys Ingersoll unsigned char *n, 68247e946e7SWyllys Ingersoll int size_p, 68347e946e7SWyllys Ingersoll unsigned char *p, 68447e946e7SWyllys Ingersoll TSS_HKEY hParentKey, 68547e946e7SWyllys Ingersoll TSS_FLAG initFlags, 68647e946e7SWyllys Ingersoll TSS_HKEY *phKey) 68747e946e7SWyllys Ingersoll { 68847e946e7SWyllys Ingersoll TSS_RESULT result; 68947e946e7SWyllys Ingersoll UINT32 key_size; 69047e946e7SWyllys Ingersoll 69147e946e7SWyllys Ingersoll key_size = util_get_keysize_flag(size_n * 8); 69247e946e7SWyllys Ingersoll if (initFlags == 0) { 69347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 69447e946e7SWyllys Ingersoll } 69547e946e7SWyllys Ingersoll 69647e946e7SWyllys Ingersoll /* create the TSS key object */ 69747e946e7SWyllys Ingersoll result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, 69847e946e7SWyllys Ingersoll TSS_KEY_MIGRATABLE | initFlags | key_size, phKey); 69947e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 70047e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 70147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 70247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 70347e946e7SWyllys Ingersoll } 70447e946e7SWyllys Ingersoll 70547e946e7SWyllys Ingersoll result = set_public_modulus(hContext, *phKey, size_n, n); 70647e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 70747e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 70847e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 70947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 71047e946e7SWyllys Ingersoll } 71147e946e7SWyllys Ingersoll 71247e946e7SWyllys Ingersoll /* set the private key data in the TSS object */ 71347e946e7SWyllys Ingersoll result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, 71447e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p); 71547e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 71647e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%x - %s", 71747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 71847e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 71947e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 72047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 72147e946e7SWyllys Ingersoll } 72247e946e7SWyllys Ingersoll 723ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION, 724ab8176c2SWyllys Ingersoll *phKey, NULL); 72547e946e7SWyllys Ingersoll 72647e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { 72747e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(*phKey, 72847e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, 72947e946e7SWyllys Ingersoll TSS_ES_RSAESPKCSV15))) { 73047e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", 73147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 73247e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 73347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 73447e946e7SWyllys Ingersoll } 73547e946e7SWyllys Ingersoll 73647e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(*phKey, 73747e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, 73847e946e7SWyllys Ingersoll TSS_SS_RSASSAPKCS1V15_DER))) { 73947e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", 74047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 74147e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 74247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 74347e946e7SWyllys Ingersoll } 74447e946e7SWyllys Ingersoll } 74547e946e7SWyllys Ingersoll 74647e946e7SWyllys Ingersoll result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS); 74747e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 74847e946e7SWyllys Ingersoll stlogit("Tspi_Key_WrapKey: 0x%0x - %s", 74947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 75047e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 75147e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 75247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 75347e946e7SWyllys Ingersoll } 75447e946e7SWyllys Ingersoll 75547e946e7SWyllys Ingersoll return (CKR_OK); 75647e946e7SWyllys Ingersoll } 75747e946e7SWyllys Ingersoll 75847e946e7SWyllys Ingersoll /* 75947e946e7SWyllys Ingersoll * Create a TPM key blob for an imported key. This function is only called when 76047e946e7SWyllys Ingersoll * a key is in active use, so any failure should trickle through. 76147e946e7SWyllys Ingersoll */ 76247e946e7SWyllys Ingersoll static CK_RV 76347e946e7SWyllys Ingersoll token_wrap_key_object(TSS_HCONTEXT hContext, 76447e946e7SWyllys Ingersoll CK_OBJECT_HANDLE ckObject, 76547e946e7SWyllys Ingersoll TSS_HKEY hParentKey, TSS_HKEY *phKey) 76647e946e7SWyllys Ingersoll { 76747e946e7SWyllys Ingersoll CK_RV rc = CKR_OK; 76847e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr = NULL, *new_attr, *prime_attr; 76947e946e7SWyllys Ingersoll CK_ULONG class, key_type; 77047e946e7SWyllys Ingersoll OBJECT *obj; 77147e946e7SWyllys Ingersoll 77247e946e7SWyllys Ingersoll TSS_RESULT result; 77347e946e7SWyllys Ingersoll TSS_FLAG initFlags = 0; 77447e946e7SWyllys Ingersoll BYTE *rgbBlob; 77547e946e7SWyllys Ingersoll UINT32 ulBlobLen; 77647e946e7SWyllys Ingersoll 77747e946e7SWyllys Ingersoll if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) { 77847e946e7SWyllys Ingersoll return (rc); 77947e946e7SWyllys Ingersoll } 78047e946e7SWyllys Ingersoll 78147e946e7SWyllys Ingersoll /* if the object isn't a key, fail */ 78247e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_KEY_TYPE, 78347e946e7SWyllys Ingersoll &attr) == FALSE) { 78447e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 78547e946e7SWyllys Ingersoll } 78647e946e7SWyllys Ingersoll 78747e946e7SWyllys Ingersoll key_type = *((CK_ULONG *)attr->pValue); 78847e946e7SWyllys Ingersoll 78947e946e7SWyllys Ingersoll if (key_type != CKK_RSA) { 79047e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 79147e946e7SWyllys Ingersoll } 79247e946e7SWyllys Ingersoll 79347e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_CLASS, 79447e946e7SWyllys Ingersoll &attr) == FALSE) { 79547e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 79647e946e7SWyllys Ingersoll } 79747e946e7SWyllys Ingersoll 79847e946e7SWyllys Ingersoll class = *((CK_ULONG *)attr->pValue); 79947e946e7SWyllys Ingersoll 80047e946e7SWyllys Ingersoll if (class == CKO_PRIVATE_KEY) { 80147e946e7SWyllys Ingersoll /* 80247e946e7SWyllys Ingersoll * In order to create a full TSS key blob using a PKCS#11 80347e946e7SWyllys Ingersoll * private key object, we need one of the two primes, the 80447e946e7SWyllys Ingersoll * modulus and the private exponent and we need the public 80547e946e7SWyllys Ingersoll * exponent to be correct. 80647e946e7SWyllys Ingersoll */ 80747e946e7SWyllys Ingersoll 80847e946e7SWyllys Ingersoll /* 80947e946e7SWyllys Ingersoll * Check the least likely attribute to exist first, the 81047e946e7SWyllys Ingersoll * primes. 81147e946e7SWyllys Ingersoll */ 81247e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_PRIME_1, 81347e946e7SWyllys Ingersoll &prime_attr) == FALSE) { 81447e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, 81547e946e7SWyllys Ingersoll CKA_PRIME_2, &prime_attr) == FALSE) { 81647e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 81747e946e7SWyllys Ingersoll } 81847e946e7SWyllys Ingersoll } 81947e946e7SWyllys Ingersoll 82047e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 82147e946e7SWyllys Ingersoll if ((rc = util_check_public_exponent(obj->template))) { 82247e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 82347e946e7SWyllys Ingersoll } 82447e946e7SWyllys Ingersoll 82547e946e7SWyllys Ingersoll /* get the modulus */ 82647e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_MODULUS, 82747e946e7SWyllys Ingersoll &attr) == FALSE) { 82847e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 82947e946e7SWyllys Ingersoll } 83047e946e7SWyllys Ingersoll 83147e946e7SWyllys Ingersoll /* make sure the key size is usable */ 83247e946e7SWyllys Ingersoll initFlags = util_get_keysize_flag(attr->ulValueLen * 8); 83347e946e7SWyllys Ingersoll if (initFlags == 0) { 83447e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 83547e946e7SWyllys Ingersoll } 83647e946e7SWyllys Ingersoll 83747e946e7SWyllys Ingersoll /* generate the software based key */ 83847e946e7SWyllys Ingersoll if ((rc = token_wrap_sw_key(hContext, 83947e946e7SWyllys Ingersoll (int)attr->ulValueLen, attr->pValue, 84047e946e7SWyllys Ingersoll (int)prime_attr->ulValueLen, prime_attr->pValue, 84147e946e7SWyllys Ingersoll hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION, 84247e946e7SWyllys Ingersoll phKey))) { 84347e946e7SWyllys Ingersoll return (rc); 84447e946e7SWyllys Ingersoll } 84547e946e7SWyllys Ingersoll } else if (class == CKO_PUBLIC_KEY) { 84647e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 84747e946e7SWyllys Ingersoll if ((util_check_public_exponent(obj->template))) { 84847e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 84947e946e7SWyllys Ingersoll } 85047e946e7SWyllys Ingersoll 85147e946e7SWyllys Ingersoll /* grab the modulus to put into the TSS key object */ 85247e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, 85347e946e7SWyllys Ingersoll CKA_MODULUS, &attr) == FALSE) { 85447e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 85547e946e7SWyllys Ingersoll } 85647e946e7SWyllys Ingersoll 85747e946e7SWyllys Ingersoll /* make sure the key size is usable */ 85847e946e7SWyllys Ingersoll initFlags = util_get_keysize_flag(attr->ulValueLen * 8); 85947e946e7SWyllys Ingersoll if (initFlags == 0) { 86047e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 86147e946e7SWyllys Ingersoll } 86247e946e7SWyllys Ingersoll 863ab8176c2SWyllys Ingersoll initFlags |= TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION | 864ab8176c2SWyllys Ingersoll TSS_KEY_TYPE_LEGACY; 86547e946e7SWyllys Ingersoll 86647e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 86747e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { 86847e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 86947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 87047e946e7SWyllys Ingersoll return (result); 87147e946e7SWyllys Ingersoll } 87247e946e7SWyllys Ingersoll 87347e946e7SWyllys Ingersoll if ((result = set_public_modulus(hContext, *phKey, 87447e946e7SWyllys Ingersoll attr->ulValueLen, attr->pValue))) { 87547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 87647e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 87747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 87847e946e7SWyllys Ingersoll } 879ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, 880ab8176c2SWyllys Ingersoll TSS_POLICY_MIGRATION, *phKey, NULL); 881ab8176c2SWyllys Ingersoll if (result) { 882ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 883ab8176c2SWyllys Ingersoll *phKey = NULL_HKEY; 884ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 885ab8176c2SWyllys Ingersoll } 886ab8176c2SWyllys Ingersoll 887ab8176c2SWyllys Ingersoll result = set_legacy_key_params(*phKey); 888ab8176c2SWyllys Ingersoll if (result) { 889ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 890ab8176c2SWyllys Ingersoll *phKey = NULL_HKEY; 891ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 892ab8176c2SWyllys Ingersoll } 89347e946e7SWyllys Ingersoll } else { 89447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 89547e946e7SWyllys Ingersoll } 89647e946e7SWyllys Ingersoll 89747e946e7SWyllys Ingersoll /* grab the entire key blob to put into the PKCS#11 object */ 89847e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, 89947e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { 90047e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 90147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 90247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 90347e946e7SWyllys Ingersoll } 90447e946e7SWyllys Ingersoll 90547e946e7SWyllys Ingersoll /* insert the key blob into the object */ 90647e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, 90747e946e7SWyllys Ingersoll &new_attr))) { 90847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 90947e946e7SWyllys Ingersoll return (rc); 91047e946e7SWyllys Ingersoll } 91147e946e7SWyllys Ingersoll (void) template_update_attribute(obj->template, new_attr); 91247e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 91347e946e7SWyllys Ingersoll 91447e946e7SWyllys Ingersoll /* 91547e946e7SWyllys Ingersoll * If this is a token object, save it with the new attribute 91647e946e7SWyllys Ingersoll * so that we don't have to go down this path again. 91747e946e7SWyllys Ingersoll */ 91847e946e7SWyllys Ingersoll if (!object_is_session_object(obj)) { 91947e946e7SWyllys Ingersoll rc = save_token_object(hContext, obj); 92047e946e7SWyllys Ingersoll } 92147e946e7SWyllys Ingersoll 92247e946e7SWyllys Ingersoll return (rc); 92347e946e7SWyllys Ingersoll } 92447e946e7SWyllys Ingersoll 92547e946e7SWyllys Ingersoll static TSS_RESULT 926ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_FLAG policyType, 927ab8176c2SWyllys Ingersoll TSS_HKEY hKey, CK_CHAR *passHash) 92847e946e7SWyllys Ingersoll { 92947e946e7SWyllys Ingersoll TSS_RESULT result; 93047e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 93147e946e7SWyllys Ingersoll 93247e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 933ab8176c2SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, policyType, &hPolicy))) { 93447e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 93547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 93647e946e7SWyllys Ingersoll return (result); 93747e946e7SWyllys Ingersoll } 93847e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) { 93947e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", 94047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 94147e946e7SWyllys Ingersoll goto done; 94247e946e7SWyllys Ingersoll } 94347e946e7SWyllys Ingersoll if (passHash == NULL) { 94447e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 94547e946e7SWyllys Ingersoll 0, NULL); 94647e946e7SWyllys Ingersoll } else { 94747e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 94847e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, passHash); 94947e946e7SWyllys Ingersoll } 95047e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 95147e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 95247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 95347e946e7SWyllys Ingersoll goto done; 95447e946e7SWyllys Ingersoll } 95547e946e7SWyllys Ingersoll done: 95647e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) 95747e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPolicy); 95847e946e7SWyllys Ingersoll return (result); 95947e946e7SWyllys Ingersoll } 96047e946e7SWyllys Ingersoll 96147e946e7SWyllys Ingersoll /* 96247e946e7SWyllys Ingersoll * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped 96347e946e7SWyllys Ingersoll * by an already TPM-resident key and protected with a PIN (optional). 96447e946e7SWyllys Ingersoll */ 96547e946e7SWyllys Ingersoll static CK_RV 96647e946e7SWyllys Ingersoll token_load_key( 96747e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 96847e946e7SWyllys Ingersoll CK_OBJECT_HANDLE ckKey, 96947e946e7SWyllys Ingersoll TSS_HKEY hParentKey, 97047e946e7SWyllys Ingersoll CK_CHAR_PTR passHash, 97147e946e7SWyllys Ingersoll TSS_HKEY *phKey) 97247e946e7SWyllys Ingersoll { 97347e946e7SWyllys Ingersoll TSS_RESULT result; 97447e946e7SWyllys Ingersoll CK_RV rc; 97547e946e7SWyllys Ingersoll 97647e946e7SWyllys Ingersoll /* 97747e946e7SWyllys Ingersoll * The key blob wasn't found, load the parts of the key 97847e946e7SWyllys Ingersoll * from the object DB and create a new key object that 97947e946e7SWyllys Ingersoll * gets loaded into the TPM, wrapped with the parent key. 98047e946e7SWyllys Ingersoll */ 98147e946e7SWyllys Ingersoll if ((rc = token_wrap_key_object(hContext, ckKey, 98247e946e7SWyllys Ingersoll hParentKey, phKey))) { 98347e946e7SWyllys Ingersoll return (rc); 98447e946e7SWyllys Ingersoll } 98547e946e7SWyllys Ingersoll 98647e946e7SWyllys Ingersoll /* 98747e946e7SWyllys Ingersoll * Assign the PIN hash (optional) to the newly loaded key object, 98847e946e7SWyllys Ingersoll * if this PIN is incorrect, the TPM will not be able to decrypt 98947e946e7SWyllys Ingersoll * the private key and use it. 99047e946e7SWyllys Ingersoll */ 991ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 992ab8176c2SWyllys Ingersoll *phKey, passHash); 993ab8176c2SWyllys Ingersoll 99447e946e7SWyllys Ingersoll return (result); 99547e946e7SWyllys Ingersoll } 99647e946e7SWyllys Ingersoll 99747e946e7SWyllys Ingersoll /* 99847e946e7SWyllys Ingersoll * Load the SRK into the TPM by referencing its well-known UUID and using the 99947e946e7SWyllys Ingersoll * default SRK PIN (20 bytes of 0x00). 100047e946e7SWyllys Ingersoll * 100147e946e7SWyllys Ingersoll * NOTE - if the SRK PIN is changed by an administrative tool, this code will 100247e946e7SWyllys Ingersoll * fail because it assumes that the well-known PIN is still being used. 100347e946e7SWyllys Ingersoll */ 100447e946e7SWyllys Ingersoll static TSS_RESULT 100547e946e7SWyllys Ingersoll token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK) 100647e946e7SWyllys Ingersoll { 100747e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 100847e946e7SWyllys Ingersoll TSS_RESULT result; 100947e946e7SWyllys Ingersoll TSS_UUID SRK_UUID = TSS_UUID_SRK; 101047e946e7SWyllys Ingersoll BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET; 101147e946e7SWyllys Ingersoll TSS_HTPM hTPM; 101247e946e7SWyllys Ingersoll 101347e946e7SWyllys Ingersoll if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) { 101447e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", 101547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 101647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 101747e946e7SWyllys Ingersoll } 101847e946e7SWyllys Ingersoll 101947e946e7SWyllys Ingersoll /* load the SRK */ 102047e946e7SWyllys Ingersoll if ((result = Tspi_Context_LoadKeyByUUID(hContext, 102147e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) { 102247e946e7SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s", 102347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 102447e946e7SWyllys Ingersoll goto done; 102547e946e7SWyllys Ingersoll } 102647e946e7SWyllys Ingersoll if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE, 102747e946e7SWyllys Ingersoll &hPolicy))) { 102847e946e7SWyllys Ingersoll stlogit("Tspi_GetPolicyObject: 0x%0x - %s", 102947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 103047e946e7SWyllys Ingersoll goto done; 103147e946e7SWyllys Ingersoll } 103247e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 103347e946e7SWyllys Ingersoll sizeof (wellKnown), wellKnown))) { 103447e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 103547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 103647e946e7SWyllys Ingersoll goto done; 103747e946e7SWyllys Ingersoll } 103847e946e7SWyllys Ingersoll 103947e946e7SWyllys Ingersoll done: 104047e946e7SWyllys Ingersoll return (result); 104147e946e7SWyllys Ingersoll } 104247e946e7SWyllys Ingersoll 104347e946e7SWyllys Ingersoll static TSS_RESULT 104447e946e7SWyllys Ingersoll tss_find_and_load_key(TSS_HCONTEXT hContext, 104547e946e7SWyllys Ingersoll char *keyid, TSS_UUID *uuid, TSS_HKEY hParent, 104647e946e7SWyllys Ingersoll BYTE *hash, TSS_HKEY *hKey) 104747e946e7SWyllys Ingersoll { 104847e946e7SWyllys Ingersoll TSS_RESULT result; 104947e946e7SWyllys Ingersoll 105047e946e7SWyllys Ingersoll if (local_uuid_is_null(uuid) && 105147e946e7SWyllys Ingersoll find_uuid(keyid, uuid)) { 105247e946e7SWyllys Ingersoll /* The UUID was not created or saved yet */ 105347e946e7SWyllys Ingersoll return (1); 105447e946e7SWyllys Ingersoll } 105547e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 105647e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, *uuid, hKey); 105747e946e7SWyllys Ingersoll if (result) { 105847e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s", 105947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 106047e946e7SWyllys Ingersoll return (result); 106147e946e7SWyllys Ingersoll } 106247e946e7SWyllys Ingersoll 106347e946e7SWyllys Ingersoll if (hash != NULL) { 1064ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, 1065ab8176c2SWyllys Ingersoll TSS_POLICY_USAGE, *hKey, (CK_BYTE *)hash); 106647e946e7SWyllys Ingersoll if (result) 106747e946e7SWyllys Ingersoll return (result); 106847e946e7SWyllys Ingersoll } 106947e946e7SWyllys Ingersoll 107047e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(*hKey, hParent); 107147e946e7SWyllys Ingersoll if (result) 107247e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 107347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 107447e946e7SWyllys Ingersoll 107547e946e7SWyllys Ingersoll return (result); 107647e946e7SWyllys Ingersoll } 107747e946e7SWyllys Ingersoll 107847e946e7SWyllys Ingersoll static TSS_RESULT 107947e946e7SWyllys Ingersoll token_load_public_root_key(TSS_HCONTEXT hContext) 108047e946e7SWyllys Ingersoll { 108147e946e7SWyllys Ingersoll TSS_RESULT result; 108247e946e7SWyllys Ingersoll TSS_HKEY hSRK; 108347e946e7SWyllys Ingersoll 108447e946e7SWyllys Ingersoll if (hPublicRootKey != NULL_HKEY) 108547e946e7SWyllys Ingersoll return (TSS_SUCCESS); 108647e946e7SWyllys Ingersoll 108747e946e7SWyllys Ingersoll if ((result = token_load_srk(hContext, &hSRK))) { 108847e946e7SWyllys Ingersoll return (result); 108947e946e7SWyllys Ingersoll } 109047e946e7SWyllys Ingersoll 109147e946e7SWyllys Ingersoll result = tss_find_and_load_key(hContext, 109247e946e7SWyllys Ingersoll TPMTOK_PUBLIC_ROOT_KEY_ID, 109347e946e7SWyllys Ingersoll &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey); 109447e946e7SWyllys Ingersoll if (result) 109547e946e7SWyllys Ingersoll return (result); 109647e946e7SWyllys Ingersoll 109747e946e7SWyllys Ingersoll return (result); 109847e946e7SWyllys Ingersoll } 109947e946e7SWyllys Ingersoll 110047e946e7SWyllys Ingersoll static TSS_RESULT 1101ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY hKey) 1102ab8176c2SWyllys Ingersoll { 1103ab8176c2SWyllys Ingersoll TSS_RESULT result; 1104ab8176c2SWyllys Ingersoll 1105ab8176c2SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(hKey, 1106ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, 1107ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_ENCSCHEME, 1108ab8176c2SWyllys Ingersoll TSS_ES_RSAESPKCSV15))) { 1109ab8176c2SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s", 1110ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 1111ab8176c2SWyllys Ingersoll return (result); 1112ab8176c2SWyllys Ingersoll } 1113ab8176c2SWyllys Ingersoll 1114ab8176c2SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(hKey, 1115ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, 1116ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_SIGSCHEME, 1117ab8176c2SWyllys Ingersoll TSS_SS_RSASSAPKCS1V15_DER))) { 1118ab8176c2SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s", 1119ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 1120ab8176c2SWyllys Ingersoll return (result); 1121ab8176c2SWyllys Ingersoll } 1122ab8176c2SWyllys Ingersoll 1123ab8176c2SWyllys Ingersoll return (result); 1124ab8176c2SWyllys Ingersoll } 1125ab8176c2SWyllys Ingersoll 1126ab8176c2SWyllys Ingersoll static TSS_RESULT 112747e946e7SWyllys Ingersoll tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash, 112847e946e7SWyllys Ingersoll TSS_HKEY hParentKey, TSS_HKEY *phKey) 112947e946e7SWyllys Ingersoll { 113047e946e7SWyllys Ingersoll TSS_RESULT result; 113147e946e7SWyllys Ingersoll TSS_HPOLICY hMigPolicy; 113247e946e7SWyllys Ingersoll 113347e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 113447e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { 113547e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 113647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 113747e946e7SWyllys Ingersoll return (result); 113847e946e7SWyllys Ingersoll } 1139ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 1140ab8176c2SWyllys Ingersoll *phKey, passHash); 114147e946e7SWyllys Ingersoll 114247e946e7SWyllys Ingersoll if (result) { 114347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 114447e946e7SWyllys Ingersoll return (result); 114547e946e7SWyllys Ingersoll } 114647e946e7SWyllys Ingersoll 114747e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) { 114847e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 114947e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, 115047e946e7SWyllys Ingersoll &hMigPolicy))) { 115147e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 115247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 115347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 115447e946e7SWyllys Ingersoll return (result); 115547e946e7SWyllys Ingersoll } 115647e946e7SWyllys Ingersoll 115747e946e7SWyllys Ingersoll if (passHash == NULL) { 115847e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hMigPolicy, 115947e946e7SWyllys Ingersoll TSS_SECRET_MODE_NONE, 0, NULL); 116047e946e7SWyllys Ingersoll } else { 116147e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hMigPolicy, 116247e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, 20, passHash); 116347e946e7SWyllys Ingersoll } 116447e946e7SWyllys Ingersoll 116547e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 116647e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 116747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 116847e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 116947e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 117047e946e7SWyllys Ingersoll return (result); 117147e946e7SWyllys Ingersoll } 117247e946e7SWyllys Ingersoll 117347e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) { 117447e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", 117547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 117647e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 117747e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 117847e946e7SWyllys Ingersoll return (result); 117947e946e7SWyllys Ingersoll } 118047e946e7SWyllys Ingersoll } 118147e946e7SWyllys Ingersoll 118247e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { 1183ab8176c2SWyllys Ingersoll result = set_legacy_key_params(*phKey); 1184ab8176c2SWyllys Ingersoll if (result) { 118547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 118647e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 118747e946e7SWyllys Ingersoll return (result); 118847e946e7SWyllys Ingersoll } 118947e946e7SWyllys Ingersoll } 119047e946e7SWyllys Ingersoll 119147e946e7SWyllys Ingersoll if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) { 119247e946e7SWyllys Ingersoll stlogit("Tspi_Key_CreateKey: 0x%0x - %s", 119347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 119447e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 119547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 119647e946e7SWyllys Ingersoll } 119747e946e7SWyllys Ingersoll 119847e946e7SWyllys Ingersoll return (result); 119947e946e7SWyllys Ingersoll } 120047e946e7SWyllys Ingersoll 120147e946e7SWyllys Ingersoll static TSS_RESULT 120247e946e7SWyllys Ingersoll tss_change_auth( 120347e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 120447e946e7SWyllys Ingersoll TSS_HKEY hObjectToChange, TSS_HKEY hParentObject, 120547e946e7SWyllys Ingersoll TSS_UUID objUUID, TSS_UUID parentUUID, 120647e946e7SWyllys Ingersoll CK_CHAR *passHash) 120747e946e7SWyllys Ingersoll { 120847e946e7SWyllys Ingersoll TSS_RESULT result; 120947e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 121047e946e7SWyllys Ingersoll TSS_HKEY oldkey; 121147e946e7SWyllys Ingersoll 121247e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 121347e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { 121447e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 121547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 121647e946e7SWyllys Ingersoll return (result); 121747e946e7SWyllys Ingersoll } 121847e946e7SWyllys Ingersoll 121947e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 122047e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, passHash))) { 122147e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 122247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 122347e946e7SWyllys Ingersoll return (result); 122447e946e7SWyllys Ingersoll } 122547e946e7SWyllys Ingersoll 122647e946e7SWyllys Ingersoll if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject, 122747e946e7SWyllys Ingersoll hPolicy))) { 122847e946e7SWyllys Ingersoll stlogit("Tspi_ChangeAuth: 0x%0x - %s", 122947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 123047e946e7SWyllys Ingersoll } 123147e946e7SWyllys Ingersoll /* 123247e946e7SWyllys Ingersoll * Update the PS key by unregistering the key UUID and then 123347e946e7SWyllys Ingersoll * re-registering with the same UUID. This forces the updated 123447e946e7SWyllys Ingersoll * auth data associated with the key to be stored in PS so 123547e946e7SWyllys Ingersoll * the new PIN can be used next time. 123647e946e7SWyllys Ingersoll */ 123747e946e7SWyllys Ingersoll if ((result = Tspi_Context_UnregisterKey(hContext, 123847e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, objUUID, &oldkey))) 123947e946e7SWyllys Ingersoll stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s", 124047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 124147e946e7SWyllys Ingersoll 124247e946e7SWyllys Ingersoll if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange, 124347e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID))) 124447e946e7SWyllys Ingersoll stlogit("Tspi_Context_RegisterKey: 0x%0x - %s", 124547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 124647e946e7SWyllys Ingersoll 124747e946e7SWyllys Ingersoll return (result); 124847e946e7SWyllys Ingersoll } 124947e946e7SWyllys Ingersoll 125047e946e7SWyllys Ingersoll static CK_RV 125147e946e7SWyllys Ingersoll token_generate_leaf_key(TSS_HCONTEXT hContext, 125247e946e7SWyllys Ingersoll int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey) 125347e946e7SWyllys Ingersoll { 125447e946e7SWyllys Ingersoll CK_RV rc = CKR_FUNCTION_FAILED; 125547e946e7SWyllys Ingersoll TSS_RESULT result; 125647e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 125747e946e7SWyllys Ingersoll TSS_UUID newuuid, parentUUID; 125847e946e7SWyllys Ingersoll char *keyid; 125947e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_MIGRATABLE | 126047e946e7SWyllys Ingersoll TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048 | TSS_KEY_AUTHORIZATION; 126147e946e7SWyllys Ingersoll 126247e946e7SWyllys Ingersoll switch (key_type) { 126347e946e7SWyllys Ingersoll case TPMTOK_PUBLIC_LEAF_KEY: 126447e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 126547e946e7SWyllys Ingersoll keyid = TPMTOK_PUBLIC_LEAF_KEY_ID; 126647e946e7SWyllys Ingersoll local_uuid_copy(&parentUUID, &publicRootKeyUUID); 126747e946e7SWyllys Ingersoll break; 126847e946e7SWyllys Ingersoll case TPMTOK_PRIVATE_LEAF_KEY: 126947e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 127047e946e7SWyllys Ingersoll keyid = TPMTOK_PRIVATE_LEAF_KEY_ID; 127147e946e7SWyllys Ingersoll local_uuid_copy(&parentUUID, &privateRootKeyUUID); 127247e946e7SWyllys Ingersoll break; 127347e946e7SWyllys Ingersoll default: 127447e946e7SWyllys Ingersoll stlogit("Unknown key type 0x%0x", key_type); 127547e946e7SWyllys Ingersoll goto done; 127647e946e7SWyllys Ingersoll break; 127747e946e7SWyllys Ingersoll } 127847e946e7SWyllys Ingersoll 127947e946e7SWyllys Ingersoll if (result = tss_generate_key(hContext, initFlags, passHash, 128047e946e7SWyllys Ingersoll hParentKey, phKey)) { 128147e946e7SWyllys Ingersoll return (rc); 128247e946e7SWyllys Ingersoll } 128347e946e7SWyllys Ingersoll 128447e946e7SWyllys Ingersoll /* 128547e946e7SWyllys Ingersoll * - generate newUUID 128647e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 128747e946e7SWyllys Ingersoll * USER, newUUID, USER, parentUUID); 128847e946e7SWyllys Ingersoll * - store newUUID 128947e946e7SWyllys Ingersoll */ 129047e946e7SWyllys Ingersoll (void) local_uuid_generate(&newuuid); 129147e946e7SWyllys Ingersoll 129247e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, *phKey, 129347e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, newuuid, 129447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, parentUUID); 129547e946e7SWyllys Ingersoll if (result == TSS_SUCCESS) { 129647e946e7SWyllys Ingersoll int ret; 129747e946e7SWyllys Ingersoll /* 129847e946e7SWyllys Ingersoll * Add the UUID to the token UUID index. 129947e946e7SWyllys Ingersoll */ 130047e946e7SWyllys Ingersoll ret = add_uuid(keyid, &newuuid); 130147e946e7SWyllys Ingersoll 130247e946e7SWyllys Ingersoll if (ret) 130347e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 130447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, newuuid, phKey); 130547e946e7SWyllys Ingersoll else 130647e946e7SWyllys Ingersoll rc = CKR_OK; 130747e946e7SWyllys Ingersoll } 130847e946e7SWyllys Ingersoll 130947e946e7SWyllys Ingersoll done: 131047e946e7SWyllys Ingersoll return (rc); 131147e946e7SWyllys Ingersoll } 131247e946e7SWyllys Ingersoll 131347e946e7SWyllys Ingersoll /* 131447e946e7SWyllys Ingersoll * PINs are verified by attempting to bind/unbind random data using a 131547e946e7SWyllys Ingersoll * TPM resident key that has the PIN being tested assigned as its "secret". 131647e946e7SWyllys Ingersoll * If the PIN is incorrect, the unbind operation will fail. 131747e946e7SWyllys Ingersoll */ 131847e946e7SWyllys Ingersoll static CK_RV 131947e946e7SWyllys Ingersoll token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey) 132047e946e7SWyllys Ingersoll { 132147e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 132247e946e7SWyllys Ingersoll UINT32 ulUnboundDataLen; 132347e946e7SWyllys Ingersoll BYTE *rgbUnboundData = NULL; 132447e946e7SWyllys Ingersoll BYTE rgbData[16]; 132547e946e7SWyllys Ingersoll TSS_RESULT result; 132647e946e7SWyllys Ingersoll CK_RV rc = CKR_FUNCTION_FAILED; 132747e946e7SWyllys Ingersoll 132847e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 132947e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 133047e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 133147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 133247e946e7SWyllys Ingersoll goto done; 133347e946e7SWyllys Ingersoll } 133447e946e7SWyllys Ingersoll 133547e946e7SWyllys Ingersoll /* Use some random data */ 133647e946e7SWyllys Ingersoll rc = token_rng(hContext, rgbData, sizeof (rgbData)); 133747e946e7SWyllys Ingersoll if (rc) 133847e946e7SWyllys Ingersoll goto done; 133947e946e7SWyllys Ingersoll 134047e946e7SWyllys Ingersoll if ((result = Tspi_Data_Bind(hEncData, hKey, 134147e946e7SWyllys Ingersoll sizeof (rgbData), rgbData))) { 134247e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 134347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 134447e946e7SWyllys Ingersoll goto done; 134547e946e7SWyllys Ingersoll } 134647e946e7SWyllys Ingersoll 134747e946e7SWyllys Ingersoll /* unbind the junk data to test the key's auth data */ 134847e946e7SWyllys Ingersoll result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen, 134947e946e7SWyllys Ingersoll &rgbUnboundData); 1350ab8176c2SWyllys Ingersoll if (result == TPM_E_AUTHFAIL) { 135147e946e7SWyllys Ingersoll rc = CKR_PIN_INCORRECT; 135247e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 135347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 135447e946e7SWyllys Ingersoll goto done; 135547e946e7SWyllys Ingersoll } else if (result != TSS_SUCCESS) { 135647e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 135747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 135847e946e7SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 135947e946e7SWyllys Ingersoll goto done; 136047e946e7SWyllys Ingersoll } 136147e946e7SWyllys Ingersoll 136247e946e7SWyllys Ingersoll if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen)) 136347e946e7SWyllys Ingersoll rc = CKR_PIN_INCORRECT; 136447e946e7SWyllys Ingersoll else 136547e946e7SWyllys Ingersoll rc = CKR_OK; 136647e946e7SWyllys Ingersoll 136747e946e7SWyllys Ingersoll done: 136847e946e7SWyllys Ingersoll if (rgbUnboundData != NULL) 136947e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbUnboundData); 137047e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hEncData); 137147e946e7SWyllys Ingersoll return (rc); 137247e946e7SWyllys Ingersoll } 137347e946e7SWyllys Ingersoll 137447e946e7SWyllys Ingersoll static CK_RV 137547e946e7SWyllys Ingersoll token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) 137647e946e7SWyllys Ingersoll { 137747e946e7SWyllys Ingersoll CK_RV rc; 137847e946e7SWyllys Ingersoll TSS_RESULT result; 137947e946e7SWyllys Ingersoll int ret; 138047e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | 138147e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; 138247e946e7SWyllys Ingersoll TSS_UUID SRK_UUID = TSS_UUID_SRK; 138347e946e7SWyllys Ingersoll TSS_HKEY hSRK; 138447e946e7SWyllys Ingersoll 138547e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 138647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 138747e946e7SWyllys Ingersoll 138847e946e7SWyllys Ingersoll /* 138947e946e7SWyllys Ingersoll * - create UUID privateRootKeyUUID 139047e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 139147e946e7SWyllys Ingersoll * USER, privateRootKeyUUID, system, UUID_SRK); 139247e946e7SWyllys Ingersoll * - store privateRootKeyUUID in users private token space. 139347e946e7SWyllys Ingersoll */ 139447e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, 139547e946e7SWyllys Ingersoll &hPrivateRootKey))) { 139647e946e7SWyllys Ingersoll return (result); 139747e946e7SWyllys Ingersoll } 139847e946e7SWyllys Ingersoll if (local_uuid_is_null(&privateRootKeyUUID)) 139947e946e7SWyllys Ingersoll local_uuid_generate(&privateRootKeyUUID); 140047e946e7SWyllys Ingersoll 140147e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 140247e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 140347e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, SRK_UUID); 140447e946e7SWyllys Ingersoll 140547e946e7SWyllys Ingersoll if (result) { 140647e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 140747e946e7SWyllys Ingersoll return (result); 140847e946e7SWyllys Ingersoll } 140947e946e7SWyllys Ingersoll 141047e946e7SWyllys Ingersoll ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID); 141147e946e7SWyllys Ingersoll if (ret) { 141247e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 141347e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 141447e946e7SWyllys Ingersoll &hPrivateRootKey); 141547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 141647e946e7SWyllys Ingersoll } 141747e946e7SWyllys Ingersoll 141847e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) { 141947e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 142047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 142147e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 142247e946e7SWyllys Ingersoll 142347e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); 142447e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 142547e946e7SWyllys Ingersoll 142647e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 142747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 142847e946e7SWyllys Ingersoll } 142947e946e7SWyllys Ingersoll 143047e946e7SWyllys Ingersoll 143147e946e7SWyllys Ingersoll /* generate the private leaf key */ 143247e946e7SWyllys Ingersoll if ((rc = token_generate_leaf_key(hContext, 143347e946e7SWyllys Ingersoll TPMTOK_PRIVATE_LEAF_KEY, 143447e946e7SWyllys Ingersoll pinHash, &hPrivateLeafKey))) { 143547e946e7SWyllys Ingersoll return (rc); 143647e946e7SWyllys Ingersoll } 143747e946e7SWyllys Ingersoll 143847e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) { 143947e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 144047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 144147e946e7SWyllys Ingersoll 144247e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 144347e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateLeafKeyUUID, 144447e946e7SWyllys Ingersoll &hPrivateLeafKey); 144547e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID); 144647e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 144747e946e7SWyllys Ingersoll 144847e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 144947e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 145047e946e7SWyllys Ingersoll &hPrivateRootKey); 145147e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); 145247e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 145347e946e7SWyllys Ingersoll 145447e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 145547e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 145647e946e7SWyllys Ingersoll 145747e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateLeafKey); 145847e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 145947e946e7SWyllys Ingersoll 146047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 146147e946e7SWyllys Ingersoll } 146247e946e7SWyllys Ingersoll return (rc); 146347e946e7SWyllys Ingersoll } 146447e946e7SWyllys Ingersoll 146547e946e7SWyllys Ingersoll static CK_RV 146647e946e7SWyllys Ingersoll token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) 146747e946e7SWyllys Ingersoll { 146847e946e7SWyllys Ingersoll CK_RV rc; 146947e946e7SWyllys Ingersoll TSS_RESULT result; 147047e946e7SWyllys Ingersoll int ret; 147147e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | 147247e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; 147347e946e7SWyllys Ingersoll TSS_UUID srk_uuid = TSS_UUID_SRK; 147447e946e7SWyllys Ingersoll TSS_HKEY hSRK; 147547e946e7SWyllys Ingersoll 147647e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 147747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 147847e946e7SWyllys Ingersoll 147947e946e7SWyllys Ingersoll /* 148047e946e7SWyllys Ingersoll * - create publicRootKeyUUID 148147e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPublicRootKey, 148247e946e7SWyllys Ingersoll * USER, publicRootKeyUUID, system, UUID_SRK); 148347e946e7SWyllys Ingersoll * - store publicRootKeyUUID in users private token space. 148447e946e7SWyllys Ingersoll */ 148547e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, 148647e946e7SWyllys Ingersoll &hPublicRootKey))) { 148747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 148847e946e7SWyllys Ingersoll } 148947e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID)) 149047e946e7SWyllys Ingersoll local_uuid_generate(&publicRootKeyUUID); 149147e946e7SWyllys Ingersoll 149247e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, hPublicRootKey, 149347e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 149447e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, srk_uuid); 149547e946e7SWyllys Ingersoll 149647e946e7SWyllys Ingersoll if (result) { 149747e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 149847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 149947e946e7SWyllys Ingersoll } 150047e946e7SWyllys Ingersoll 150147e946e7SWyllys Ingersoll ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID); 150247e946e7SWyllys Ingersoll if (ret) { 150347e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 150447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 150547e946e7SWyllys Ingersoll &hPublicRootKey); 150647e946e7SWyllys Ingersoll /* does result matter here? */ 150747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 150847e946e7SWyllys Ingersoll } 150947e946e7SWyllys Ingersoll 151047e946e7SWyllys Ingersoll /* Load the newly created publicRootKey into the TPM using the SRK */ 151147e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) { 151247e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%x - %s", result, 151347e946e7SWyllys Ingersoll Trspi_Error_String(result)); 151447e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 151547e946e7SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 151647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 151747e946e7SWyllys Ingersoll } 151847e946e7SWyllys Ingersoll 151947e946e7SWyllys Ingersoll /* create the SO's leaf key */ 152047e946e7SWyllys Ingersoll if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY, 152147e946e7SWyllys Ingersoll pinHash, &hPublicLeafKey))) { 152247e946e7SWyllys Ingersoll return (rc); 152347e946e7SWyllys Ingersoll } 152447e946e7SWyllys Ingersoll 152547e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) { 152647e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 152747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 152847e946e7SWyllys Ingersoll 152947e946e7SWyllys Ingersoll /* Unregister keys and clear UUIDs */ 153047e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 153147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicLeafKeyUUID, 153247e946e7SWyllys Ingersoll &hPublicLeafKey); 153347e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID); 153447e946e7SWyllys Ingersoll 153547e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 153647e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 153747e946e7SWyllys Ingersoll &hPublicRootKey); 153847e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID); 153947e946e7SWyllys Ingersoll 154047e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 154147e946e7SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 154247e946e7SWyllys Ingersoll 154347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicLeafKey); 154447e946e7SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 154547e946e7SWyllys Ingersoll 154647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 154747e946e7SWyllys Ingersoll } 154847e946e7SWyllys Ingersoll 154947e946e7SWyllys Ingersoll return (rc); 155047e946e7SWyllys Ingersoll } 155147e946e7SWyllys Ingersoll 155247e946e7SWyllys Ingersoll CK_RV 155347e946e7SWyllys Ingersoll token_specific_login( 155447e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 155547e946e7SWyllys Ingersoll CK_USER_TYPE userType, 155647e946e7SWyllys Ingersoll CK_CHAR_PTR pPin, 155747e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 155847e946e7SWyllys Ingersoll { 155947e946e7SWyllys Ingersoll CK_RV rc; 156047e946e7SWyllys Ingersoll CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; 156147e946e7SWyllys Ingersoll TSS_RESULT result; 156247e946e7SWyllys Ingersoll TSS_HKEY hSRK; 156347e946e7SWyllys Ingersoll 156447e946e7SWyllys Ingersoll /* Make sure the SRK is loaded into the TPM */ 156547e946e7SWyllys Ingersoll if ((result = token_load_srk(hContext, &hSRK))) { 156647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 156747e946e7SWyllys Ingersoll } 156847e946e7SWyllys Ingersoll 156947e946e7SWyllys Ingersoll if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { 157047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 157147e946e7SWyllys Ingersoll } 157247e946e7SWyllys Ingersoll 157347e946e7SWyllys Ingersoll if (userType == CKU_USER) { 157447e946e7SWyllys Ingersoll /* 157547e946e7SWyllys Ingersoll * If the public root key doesn't exist yet, 157647e946e7SWyllys Ingersoll * the SO hasn't init'd the token. 157747e946e7SWyllys Ingersoll */ 157847e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) { 157947e946e7SWyllys Ingersoll if (result == TPM_E_DECRYPT_ERROR) { 158047e946e7SWyllys Ingersoll return (CKR_USER_PIN_NOT_INITIALIZED); 158147e946e7SWyllys Ingersoll } 158247e946e7SWyllys Ingersoll } 158347e946e7SWyllys Ingersoll 158447e946e7SWyllys Ingersoll /* 158547e946e7SWyllys Ingersoll * - find privateRootKeyUUID 158647e946e7SWyllys Ingersoll * - load by UUID (SRK parent) 158747e946e7SWyllys Ingersoll */ 158847e946e7SWyllys Ingersoll if (local_uuid_is_null(&privateRootKeyUUID) && 158947e946e7SWyllys Ingersoll find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, 159047e946e7SWyllys Ingersoll &privateRootKeyUUID)) { 159147e946e7SWyllys Ingersoll if (memcmp(hash_sha, 159247e946e7SWyllys Ingersoll default_user_pin_sha, 159347e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 159447e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 159547e946e7SWyllys Ingersoll 159647e946e7SWyllys Ingersoll not_initialized = 1; 159747e946e7SWyllys Ingersoll return (CKR_OK); 159847e946e7SWyllys Ingersoll } 159947e946e7SWyllys Ingersoll 160047e946e7SWyllys Ingersoll if ((rc = verify_user_pin(hContext, hash_sha))) { 160147e946e7SWyllys Ingersoll return (rc); 160247e946e7SWyllys Ingersoll } 160347e946e7SWyllys Ingersoll 160447e946e7SWyllys Ingersoll (void) memcpy(current_user_pin_sha, hash_sha, 160547e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH); 160647e946e7SWyllys Ingersoll 160747e946e7SWyllys Ingersoll rc = load_private_token_objects(hContext); 160847e946e7SWyllys Ingersoll if (rc == CKR_OK) { 160947e946e7SWyllys Ingersoll (void) XProcLock(xproclock); 161047e946e7SWyllys Ingersoll global_shm->priv_loaded = TRUE; 161147e946e7SWyllys Ingersoll (void) XProcUnLock(xproclock); 161247e946e7SWyllys Ingersoll } 161347e946e7SWyllys Ingersoll } else { 161447e946e7SWyllys Ingersoll /* 161547e946e7SWyllys Ingersoll * SO login logic: 161647e946e7SWyllys Ingersoll * 161747e946e7SWyllys Ingersoll * - find publicRootKey UUID 161847e946e7SWyllys Ingersoll * - load by UUID wrap with hSRK from above 161947e946e7SWyllys Ingersoll */ 162047e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID) && 162147e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, 162247e946e7SWyllys Ingersoll &publicRootKeyUUID)) { 162347e946e7SWyllys Ingersoll if (memcmp(hash_sha, 162447e946e7SWyllys Ingersoll default_so_pin_sha, 162547e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 162647e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 162747e946e7SWyllys Ingersoll 162847e946e7SWyllys Ingersoll not_initialized = 1; 162947e946e7SWyllys Ingersoll return (CKR_OK); 163047e946e7SWyllys Ingersoll 163147e946e7SWyllys Ingersoll } 163247e946e7SWyllys Ingersoll if (hPublicRootKey == NULL_HKEY) { 163347e946e7SWyllys Ingersoll result = tss_find_and_load_key( 163447e946e7SWyllys Ingersoll hContext, 163547e946e7SWyllys Ingersoll TPMTOK_PUBLIC_ROOT_KEY_ID, 163647e946e7SWyllys Ingersoll &publicRootKeyUUID, hSRK, NULL, 163747e946e7SWyllys Ingersoll &hPublicRootKey); 163847e946e7SWyllys Ingersoll 163947e946e7SWyllys Ingersoll if (result) 164047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 164147e946e7SWyllys Ingersoll } 164247e946e7SWyllys Ingersoll 164347e946e7SWyllys Ingersoll /* find, load the public leaf key */ 164447e946e7SWyllys Ingersoll if (hPublicLeafKey == NULL_HKEY) { 164547e946e7SWyllys Ingersoll result = tss_find_and_load_key( 164647e946e7SWyllys Ingersoll hContext, 164747e946e7SWyllys Ingersoll TPMTOK_PUBLIC_LEAF_KEY_ID, 164847e946e7SWyllys Ingersoll &publicLeafKeyUUID, hPublicRootKey, hash_sha, 164947e946e7SWyllys Ingersoll &hPublicLeafKey); 165047e946e7SWyllys Ingersoll if (result) 165147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 165247e946e7SWyllys Ingersoll } 165347e946e7SWyllys Ingersoll 165447e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { 165547e946e7SWyllys Ingersoll return (rc); 165647e946e7SWyllys Ingersoll } 165747e946e7SWyllys Ingersoll 165847e946e7SWyllys Ingersoll (void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH); 165947e946e7SWyllys Ingersoll } 166047e946e7SWyllys Ingersoll 166147e946e7SWyllys Ingersoll return (rc); 166247e946e7SWyllys Ingersoll } 166347e946e7SWyllys Ingersoll 166447e946e7SWyllys Ingersoll CK_RV 166547e946e7SWyllys Ingersoll token_specific_logout(TSS_HCONTEXT hContext) 166647e946e7SWyllys Ingersoll { 166747e946e7SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 166847e946e7SWyllys Ingersoll Tspi_Key_UnloadKey(hPrivateLeafKey); 166947e946e7SWyllys Ingersoll hPrivateLeafKey = NULL_HKEY; 167047e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 167147e946e7SWyllys Ingersoll Tspi_Key_UnloadKey(hPublicLeafKey); 167247e946e7SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 167347e946e7SWyllys Ingersoll } 167447e946e7SWyllys Ingersoll 167547e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 167647e946e7SWyllys Ingersoll local_uuid_clear(&publicLeafKeyUUID); 167747e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 167847e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 167947e946e7SWyllys Ingersoll 168047e946e7SWyllys Ingersoll (void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH); 168147e946e7SWyllys Ingersoll (void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH); 168247e946e7SWyllys Ingersoll 168347e946e7SWyllys Ingersoll (void) object_mgr_purge_private_token_objects(hContext); 168447e946e7SWyllys Ingersoll 168547e946e7SWyllys Ingersoll return (CKR_OK); 168647e946e7SWyllys Ingersoll } 168747e946e7SWyllys Ingersoll 168847e946e7SWyllys Ingersoll /*ARGSUSED*/ 168947e946e7SWyllys Ingersoll CK_RV 169047e946e7SWyllys Ingersoll token_specific_init_pin(TSS_HCONTEXT hContext, 169147e946e7SWyllys Ingersoll CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 169247e946e7SWyllys Ingersoll { 169347e946e7SWyllys Ingersoll /* 169447e946e7SWyllys Ingersoll * Since the SO must log in before calling C_InitPIN, we will 169547e946e7SWyllys Ingersoll * be able to return (CKR_OK) automatically here. 169647e946e7SWyllys Ingersoll * This is because the USER key structure is created at the 169747e946e7SWyllys Ingersoll * time of her first login, not at C_InitPIN time. 169847e946e7SWyllys Ingersoll */ 169947e946e7SWyllys Ingersoll return (CKR_OK); 170047e946e7SWyllys Ingersoll } 170147e946e7SWyllys Ingersoll 170247e946e7SWyllys Ingersoll static CK_RV 170347e946e7SWyllys Ingersoll check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash, 170447e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 170547e946e7SWyllys Ingersoll { 170647e946e7SWyllys Ingersoll /* make sure the new PIN is different */ 170747e946e7SWyllys Ingersoll if (userType == CKU_USER) { 170847e946e7SWyllys Ingersoll if (!memcmp(pinHash, default_user_pin_sha, 170947e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 171047e946e7SWyllys Ingersoll LogError1("new PIN must not be the default"); 171147e946e7SWyllys Ingersoll return (CKR_PIN_INVALID); 171247e946e7SWyllys Ingersoll } 171347e946e7SWyllys Ingersoll } else { 171447e946e7SWyllys Ingersoll if (!memcmp(pinHash, default_so_pin_sha, 171547e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 171647e946e7SWyllys Ingersoll LogError1("new PIN must not be the default"); 171747e946e7SWyllys Ingersoll return (CKR_PIN_INVALID); 171847e946e7SWyllys Ingersoll } 171947e946e7SWyllys Ingersoll } 172047e946e7SWyllys Ingersoll 172147e946e7SWyllys Ingersoll if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) { 172247e946e7SWyllys Ingersoll LogError1("New PIN is out of size range"); 172347e946e7SWyllys Ingersoll return (CKR_PIN_LEN_RANGE); 172447e946e7SWyllys Ingersoll } 172547e946e7SWyllys Ingersoll 172647e946e7SWyllys Ingersoll return (CKR_OK); 172747e946e7SWyllys Ingersoll } 172847e946e7SWyllys Ingersoll 172947e946e7SWyllys Ingersoll /* 173047e946e7SWyllys Ingersoll * This function is called from set_pin only, where a non-logged-in public 173147e946e7SWyllys Ingersoll * session can provide the user pin which must be verified. This function 173247e946e7SWyllys Ingersoll * assumes that the pin has already been set once, so there's no migration 173347e946e7SWyllys Ingersoll * path option or checking of the default user pin. 173447e946e7SWyllys Ingersoll */ 173547e946e7SWyllys Ingersoll static CK_RV 173647e946e7SWyllys Ingersoll verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha) 173747e946e7SWyllys Ingersoll { 173847e946e7SWyllys Ingersoll CK_RV rc; 173947e946e7SWyllys Ingersoll TSS_RESULT result; 174047e946e7SWyllys Ingersoll TSS_HKEY hSRK; 174147e946e7SWyllys Ingersoll 174247e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 174347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 174447e946e7SWyllys Ingersoll 174547e946e7SWyllys Ingersoll /* 174647e946e7SWyllys Ingersoll * Verify the user by loading the privateLeafKey 174747e946e7SWyllys Ingersoll * into the TPM (if it's not already) and then 174847e946e7SWyllys Ingersoll * call the verify_pin operation. 174947e946e7SWyllys Ingersoll * 175047e946e7SWyllys Ingersoll * The hashed PIN is assigned to the private leaf key. 175147e946e7SWyllys Ingersoll * If it is incorrect (not the same as the one originally 175247e946e7SWyllys Ingersoll * used when the key was created), the verify operation 175347e946e7SWyllys Ingersoll * will fail. 175447e946e7SWyllys Ingersoll */ 175547e946e7SWyllys Ingersoll if (hPrivateRootKey == NULL_HKEY) { 175647e946e7SWyllys Ingersoll result = tss_find_and_load_key( 175747e946e7SWyllys Ingersoll hContext, 175847e946e7SWyllys Ingersoll TPMTOK_PRIVATE_ROOT_KEY_ID, 175947e946e7SWyllys Ingersoll &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey); 176047e946e7SWyllys Ingersoll if (result) 176147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 176247e946e7SWyllys Ingersoll } 176347e946e7SWyllys Ingersoll 176447e946e7SWyllys Ingersoll if (hPrivateLeafKey == NULL_HKEY) { 176547e946e7SWyllys Ingersoll result = tss_find_and_load_key( 176647e946e7SWyllys Ingersoll hContext, 176747e946e7SWyllys Ingersoll TPMTOK_PRIVATE_LEAF_KEY_ID, 176847e946e7SWyllys Ingersoll &privateLeafKeyUUID, hPrivateRootKey, hash_sha, 176947e946e7SWyllys Ingersoll &hPrivateLeafKey); 177047e946e7SWyllys Ingersoll 177147e946e7SWyllys Ingersoll if (result) 177247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 177347e946e7SWyllys Ingersoll } 177447e946e7SWyllys Ingersoll 177547e946e7SWyllys Ingersoll /* 177647e946e7SWyllys Ingersoll * Verify that the PIN is correct by attempting to wrap/unwrap some 177747e946e7SWyllys Ingersoll * random data. 177847e946e7SWyllys Ingersoll */ 177947e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) { 178047e946e7SWyllys Ingersoll return (rc); 178147e946e7SWyllys Ingersoll } 178247e946e7SWyllys Ingersoll 178347e946e7SWyllys Ingersoll return (CKR_OK); 178447e946e7SWyllys Ingersoll } 178547e946e7SWyllys Ingersoll 178647e946e7SWyllys Ingersoll CK_RV 178747e946e7SWyllys Ingersoll token_specific_set_pin(ST_SESSION_HANDLE session, 178847e946e7SWyllys Ingersoll CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, 178947e946e7SWyllys Ingersoll CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) 179047e946e7SWyllys Ingersoll { 179147e946e7SWyllys Ingersoll SESSION *sess = session_mgr_find(session.sessionh); 179247e946e7SWyllys Ingersoll CK_BYTE oldpin_hash[SHA1_DIGEST_LENGTH]; 179347e946e7SWyllys Ingersoll CK_BYTE newpin_hash[SHA1_DIGEST_LENGTH]; 179447e946e7SWyllys Ingersoll CK_RV rc; 179547e946e7SWyllys Ingersoll TSS_HKEY hSRK; 179647e946e7SWyllys Ingersoll 179747e946e7SWyllys Ingersoll if (!sess) { 179847e946e7SWyllys Ingersoll return (CKR_SESSION_HANDLE_INVALID); 179947e946e7SWyllys Ingersoll } 180047e946e7SWyllys Ingersoll 180147e946e7SWyllys Ingersoll if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) { 180247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 180347e946e7SWyllys Ingersoll } 180447e946e7SWyllys Ingersoll if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) { 180547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 180647e946e7SWyllys Ingersoll } 180747e946e7SWyllys Ingersoll 180847e946e7SWyllys Ingersoll if (token_load_srk(sess->hContext, &hSRK)) { 180947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 181047e946e7SWyllys Ingersoll } 181147e946e7SWyllys Ingersoll 181247e946e7SWyllys Ingersoll /* 181347e946e7SWyllys Ingersoll * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of 181447e946e7SWyllys Ingersoll * the user that is currently logged in, or the CKU_USER PIN 181547e946e7SWyllys Ingersoll * if the session is not logged in." 181647e946e7SWyllys Ingersoll * A non R/W session fails with CKR_SESSION_READ_ONLY. 181747e946e7SWyllys Ingersoll */ 181847e946e7SWyllys Ingersoll if (sess->session_info.state == CKS_RW_USER_FUNCTIONS || 181947e946e7SWyllys Ingersoll sess->session_info.state == CKS_RW_PUBLIC_SESSION) { 182047e946e7SWyllys Ingersoll if (not_initialized) { 182147e946e7SWyllys Ingersoll if (memcmp(oldpin_hash, default_user_pin_sha, 182247e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 182347e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 182447e946e7SWyllys Ingersoll } 182547e946e7SWyllys Ingersoll 182647e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_USER, newpin_hash, 182747e946e7SWyllys Ingersoll ulNewPinLen))) { 182847e946e7SWyllys Ingersoll return (rc); 182947e946e7SWyllys Ingersoll } 183047e946e7SWyllys Ingersoll 183147e946e7SWyllys Ingersoll if ((rc = token_create_private_tree(sess->hContext, 183247e946e7SWyllys Ingersoll newpin_hash))) { 183347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 183447e946e7SWyllys Ingersoll } 183547e946e7SWyllys Ingersoll 183647e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 183747e946e7SWyllys Ingersoll ~(CKF_USER_PIN_TO_BE_CHANGED); 183847e946e7SWyllys Ingersoll nv_token_data->token_info.flags |= 183947e946e7SWyllys Ingersoll CKF_USER_PIN_INITIALIZED; 184047e946e7SWyllys Ingersoll 184147e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 184247e946e7SWyllys Ingersoll ~(CKF_USER_PIN_TO_BE_CHANGED); 184347e946e7SWyllys Ingersoll nv_token_data->token_info.flags |= 184447e946e7SWyllys Ingersoll CKF_USER_PIN_INITIALIZED; 184547e946e7SWyllys Ingersoll 184647e946e7SWyllys Ingersoll return (save_token_data(nv_token_data)); 184747e946e7SWyllys Ingersoll } 184847e946e7SWyllys Ingersoll 184947e946e7SWyllys Ingersoll if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) { 185047e946e7SWyllys Ingersoll /* if we're already logged in, just verify the hash */ 185147e946e7SWyllys Ingersoll if (memcmp(current_user_pin_sha, oldpin_hash, 185247e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 185347e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 185447e946e7SWyllys Ingersoll } 185547e946e7SWyllys Ingersoll } else { 185647e946e7SWyllys Ingersoll if ((rc = verify_user_pin(sess->hContext, 185747e946e7SWyllys Ingersoll oldpin_hash))) { 185847e946e7SWyllys Ingersoll return (rc); 185947e946e7SWyllys Ingersoll } 186047e946e7SWyllys Ingersoll } 186147e946e7SWyllys Ingersoll 186247e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_USER, newpin_hash, 186347e946e7SWyllys Ingersoll ulNewPinLen))) 186447e946e7SWyllys Ingersoll return (rc); 186547e946e7SWyllys Ingersoll 186647e946e7SWyllys Ingersoll /* change the auth on the TSS object */ 186747e946e7SWyllys Ingersoll if (tss_change_auth(sess->hContext, 186847e946e7SWyllys Ingersoll hPrivateLeafKey, hPrivateRootKey, 186947e946e7SWyllys Ingersoll privateLeafKeyUUID, privateRootKeyUUID, 187047e946e7SWyllys Ingersoll newpin_hash)) 187147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 187247e946e7SWyllys Ingersoll 187347e946e7SWyllys Ingersoll } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { 187447e946e7SWyllys Ingersoll if (not_initialized) { 187547e946e7SWyllys Ingersoll if (memcmp(default_so_pin_sha, oldpin_hash, 187647e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 187747e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 187847e946e7SWyllys Ingersoll 187947e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_SO, 188047e946e7SWyllys Ingersoll newpin_hash, ulNewPinLen))) 188147e946e7SWyllys Ingersoll return (rc); 188247e946e7SWyllys Ingersoll 188347e946e7SWyllys Ingersoll if ((rc = token_create_public_tree(sess->hContext, 188447e946e7SWyllys Ingersoll newpin_hash))) 188547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 188647e946e7SWyllys Ingersoll 188747e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 188847e946e7SWyllys Ingersoll ~(CKF_SO_PIN_TO_BE_CHANGED); 188947e946e7SWyllys Ingersoll 189047e946e7SWyllys Ingersoll return (save_token_data(nv_token_data)); 189147e946e7SWyllys Ingersoll } 189247e946e7SWyllys Ingersoll 189347e946e7SWyllys Ingersoll if (memcmp(current_so_pin_sha, oldpin_hash, 189447e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 189547e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 189647e946e7SWyllys Ingersoll 189747e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_SO, newpin_hash, 189847e946e7SWyllys Ingersoll ulNewPinLen))) 189947e946e7SWyllys Ingersoll return (rc); 190047e946e7SWyllys Ingersoll 190147e946e7SWyllys Ingersoll /* change auth on the SO's leaf key */ 190247e946e7SWyllys Ingersoll if (tss_change_auth(sess->hContext, 190347e946e7SWyllys Ingersoll hPublicLeafKey, hPublicRootKey, 190447e946e7SWyllys Ingersoll publicLeafKeyUUID, publicRootKeyUUID, 190547e946e7SWyllys Ingersoll newpin_hash)) 190647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 190747e946e7SWyllys Ingersoll 190847e946e7SWyllys Ingersoll } else { 190947e946e7SWyllys Ingersoll rc = CKR_SESSION_READ_ONLY; 191047e946e7SWyllys Ingersoll } 191147e946e7SWyllys Ingersoll 191247e946e7SWyllys Ingersoll return (rc); 191347e946e7SWyllys Ingersoll } 191447e946e7SWyllys Ingersoll 191547e946e7SWyllys Ingersoll /* only called at token init time */ 191647e946e7SWyllys Ingersoll CK_RV 191747e946e7SWyllys Ingersoll token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin, 191847e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 191947e946e7SWyllys Ingersoll { 192047e946e7SWyllys Ingersoll CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; 192147e946e7SWyllys Ingersoll CK_RV rc; 192247e946e7SWyllys Ingersoll TSS_RESULT result; 192347e946e7SWyllys Ingersoll TSS_HKEY hSRK; 192447e946e7SWyllys Ingersoll 192547e946e7SWyllys Ingersoll if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { 192647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 192747e946e7SWyllys Ingersoll } 192847e946e7SWyllys Ingersoll if ((rc = token_load_srk(hContext, &hSRK))) { 192947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 193047e946e7SWyllys Ingersoll } 193147e946e7SWyllys Ingersoll 193247e946e7SWyllys Ingersoll /* 193347e946e7SWyllys Ingersoll * TRYME INSTEAD: 193447e946e7SWyllys Ingersoll * - find publicRootKeyUUID 193547e946e7SWyllys Ingersoll * - Load publicRootKey by UUID (SRK parent) 193647e946e7SWyllys Ingersoll * - find publicLeafKeyUUID 193747e946e7SWyllys Ingersoll * - Load publicLeafKey by UUID (publicRootKey parent) 193847e946e7SWyllys Ingersoll * - set password policy on publicLeafKey 193947e946e7SWyllys Ingersoll */ 194047e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID) && 194147e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) { 194247e946e7SWyllys Ingersoll /* 194347e946e7SWyllys Ingersoll * The SO hasn't set her PIN yet, compare the 194447e946e7SWyllys Ingersoll * login pin with the hard-coded value. 194547e946e7SWyllys Ingersoll */ 194647e946e7SWyllys Ingersoll if (memcmp(default_so_pin_sha, hash_sha, 194747e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 194847e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 194947e946e7SWyllys Ingersoll } 195047e946e7SWyllys Ingersoll return (CKR_OK); 195147e946e7SWyllys Ingersoll } 195247e946e7SWyllys Ingersoll 195347e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 195447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey); 195547e946e7SWyllys Ingersoll 195647e946e7SWyllys Ingersoll if (result) 195747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 195847e946e7SWyllys Ingersoll 195947e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(hPublicRootKey, hSRK); 196047e946e7SWyllys Ingersoll if (result) 196147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 196247e946e7SWyllys Ingersoll 196347e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicLeafKeyUUID) && 196447e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID)) 196547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 196647e946e7SWyllys Ingersoll 196747e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 196847e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey); 196947e946e7SWyllys Ingersoll if (result) 197047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 197147e946e7SWyllys Ingersoll 1972ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 1973ab8176c2SWyllys Ingersoll hPublicLeafKey, hash_sha); 197447e946e7SWyllys Ingersoll if (result) 197547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 197647e946e7SWyllys Ingersoll 197747e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey); 197847e946e7SWyllys Ingersoll if (result) 197947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 198047e946e7SWyllys Ingersoll 198147e946e7SWyllys Ingersoll /* If the hash given is wrong, the verify will fail */ 198247e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { 198347e946e7SWyllys Ingersoll return (rc); 198447e946e7SWyllys Ingersoll } 198547e946e7SWyllys Ingersoll 198647e946e7SWyllys Ingersoll return (CKR_OK); 198747e946e7SWyllys Ingersoll } 198847e946e7SWyllys Ingersoll 198947e946e7SWyllys Ingersoll CK_RV 1990ab8176c2SWyllys Ingersoll token_specific_final(TSS_HCONTEXT hContext) 199147e946e7SWyllys Ingersoll { 1992ab8176c2SWyllys Ingersoll if (hPublicRootKey != NULL_HKEY) { 1993ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 1994ab8176c2SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 1995ab8176c2SWyllys Ingersoll } 1996ab8176c2SWyllys Ingersoll if (hPublicLeafKey != NULL_HKEY) { 1997ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicLeafKey); 1998ab8176c2SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 1999ab8176c2SWyllys Ingersoll } 2000ab8176c2SWyllys Ingersoll if (hPrivateRootKey != NULL_HKEY) { 2001ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 2002ab8176c2SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 2003ab8176c2SWyllys Ingersoll } 2004ab8176c2SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 2005ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateLeafKey); 2006ab8176c2SWyllys Ingersoll hPrivateLeafKey = NULL_HKEY; 2007ab8176c2SWyllys Ingersoll } 200847e946e7SWyllys Ingersoll return (CKR_OK); 200947e946e7SWyllys Ingersoll } 201047e946e7SWyllys Ingersoll 201147e946e7SWyllys Ingersoll /* 201247e946e7SWyllys Ingersoll * Wrap the 20 bytes of auth data and store in an attribute of the two 201347e946e7SWyllys Ingersoll * keys. 201447e946e7SWyllys Ingersoll */ 201547e946e7SWyllys Ingersoll static CK_RV 201647e946e7SWyllys Ingersoll token_wrap_auth_data(TSS_HCONTEXT hContext, 201747e946e7SWyllys Ingersoll CK_BYTE *authData, TEMPLATE *publ_tmpl, 201847e946e7SWyllys Ingersoll TEMPLATE *priv_tmpl) 201947e946e7SWyllys Ingersoll { 202047e946e7SWyllys Ingersoll CK_RV rc; 202147e946e7SWyllys Ingersoll CK_ATTRIBUTE *new_attr; 202247e946e7SWyllys Ingersoll 202347e946e7SWyllys Ingersoll TSS_RESULT ret; 202447e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 202547e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 202647e946e7SWyllys Ingersoll BYTE *blob; 202747e946e7SWyllys Ingersoll UINT32 blob_size; 202847e946e7SWyllys Ingersoll 202947e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { 203047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 203147e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 203247e946e7SWyllys Ingersoll hParentKey = hPublicLeafKey; 203347e946e7SWyllys Ingersoll } else { 203447e946e7SWyllys Ingersoll hParentKey = hPrivateLeafKey; 203547e946e7SWyllys Ingersoll } 203647e946e7SWyllys Ingersoll 203747e946e7SWyllys Ingersoll /* create the encrypted data object */ 203847e946e7SWyllys Ingersoll if ((ret = Tspi_Context_CreateObject(hContext, 203947e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 204047e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 204147e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 204247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 204347e946e7SWyllys Ingersoll } 204447e946e7SWyllys Ingersoll 204547e946e7SWyllys Ingersoll if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH, 204647e946e7SWyllys Ingersoll authData))) { 204747e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 204847e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 204947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 205047e946e7SWyllys Ingersoll } 205147e946e7SWyllys Ingersoll 205247e946e7SWyllys Ingersoll /* pull the encrypted data out of the encrypted data object */ 205347e946e7SWyllys Ingersoll if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, 205447e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) { 205547e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 205647e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 205747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 205847e946e7SWyllys Ingersoll } 205947e946e7SWyllys Ingersoll 206047e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size, 206147e946e7SWyllys Ingersoll &new_attr))) { 206247e946e7SWyllys Ingersoll return (rc); 206347e946e7SWyllys Ingersoll } 206447e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, new_attr); 206547e946e7SWyllys Ingersoll 206647e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, 206747e946e7SWyllys Ingersoll blob_size, &new_attr))) { 206847e946e7SWyllys Ingersoll return (rc); 206947e946e7SWyllys Ingersoll } 207047e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, new_attr); 207147e946e7SWyllys Ingersoll 207247e946e7SWyllys Ingersoll return (rc); 207347e946e7SWyllys Ingersoll } 207447e946e7SWyllys Ingersoll 207547e946e7SWyllys Ingersoll static CK_RV 207647e946e7SWyllys Ingersoll token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData, 207747e946e7SWyllys Ingersoll CK_ULONG encAuthDataLen, TSS_HKEY hKey, 207847e946e7SWyllys Ingersoll BYTE **authData) 207947e946e7SWyllys Ingersoll { 208047e946e7SWyllys Ingersoll TSS_RESULT result; 208147e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 208247e946e7SWyllys Ingersoll BYTE *buf; 208347e946e7SWyllys Ingersoll UINT32 buf_size; 208447e946e7SWyllys Ingersoll 208547e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 208647e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 208747e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 208847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 208947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 209047e946e7SWyllys Ingersoll } 209147e946e7SWyllys Ingersoll 209247e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribData(hEncData, 209347e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, 209447e946e7SWyllys Ingersoll encAuthDataLen, encAuthData))) { 209547e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 209647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 209747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 209847e946e7SWyllys Ingersoll } 209947e946e7SWyllys Ingersoll 210047e946e7SWyllys Ingersoll /* unbind the data, receiving the plaintext back */ 210147e946e7SWyllys Ingersoll if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { 210247e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 210347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 210447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 210547e946e7SWyllys Ingersoll } 210647e946e7SWyllys Ingersoll 210747e946e7SWyllys Ingersoll if (buf_size != SHA1_DIGEST_LENGTH) { 210847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 210947e946e7SWyllys Ingersoll } 211047e946e7SWyllys Ingersoll 211147e946e7SWyllys Ingersoll *authData = buf; 211247e946e7SWyllys Ingersoll 211347e946e7SWyllys Ingersoll return (CKR_OK); 211447e946e7SWyllys Ingersoll } 211547e946e7SWyllys Ingersoll 211647e946e7SWyllys Ingersoll CK_RV 211747e946e7SWyllys Ingersoll token_specific_rsa_generate_keypair( 211847e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 211947e946e7SWyllys Ingersoll TEMPLATE *publ_tmpl, 212047e946e7SWyllys Ingersoll TEMPLATE *priv_tmpl) 212147e946e7SWyllys Ingersoll { 212247e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr = NULL; 212347e946e7SWyllys Ingersoll CK_ULONG mod_bits = 0; 212447e946e7SWyllys Ingersoll CK_BBOOL flag; 212547e946e7SWyllys Ingersoll CK_RV rc; 212647e946e7SWyllys Ingersoll 212747e946e7SWyllys Ingersoll TSS_FLAG initFlags = 0; 212847e946e7SWyllys Ingersoll BYTE authHash[SHA1_DIGEST_LENGTH]; 212947e946e7SWyllys Ingersoll BYTE *authData = NULL; 213047e946e7SWyllys Ingersoll TSS_HKEY hKey = NULL_HKEY; 213147e946e7SWyllys Ingersoll TSS_HKEY hParentKey = NULL_HKEY; 213247e946e7SWyllys Ingersoll TSS_RESULT result; 213347e946e7SWyllys Ingersoll UINT32 ulBlobLen; 213447e946e7SWyllys Ingersoll BYTE *rgbBlob; 213547e946e7SWyllys Ingersoll 213647e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 213747e946e7SWyllys Ingersoll if ((util_check_public_exponent(publ_tmpl))) { 213847e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 213947e946e7SWyllys Ingersoll } 214047e946e7SWyllys Ingersoll 214147e946e7SWyllys Ingersoll flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr); 214247e946e7SWyllys Ingersoll if (!flag) { 214347e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 214447e946e7SWyllys Ingersoll } 214547e946e7SWyllys Ingersoll mod_bits = *(CK_ULONG *)attr->pValue; 214647e946e7SWyllys Ingersoll 214747e946e7SWyllys Ingersoll if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) { 214847e946e7SWyllys Ingersoll return (CKR_KEY_SIZE_RANGE); 214947e946e7SWyllys Ingersoll } 215047e946e7SWyllys Ingersoll 215147e946e7SWyllys Ingersoll /* 215247e946e7SWyllys Ingersoll * If we're not logged in, hPrivateLeafKey and hPublicLeafKey 215347e946e7SWyllys Ingersoll * should be NULL. 215447e946e7SWyllys Ingersoll */ 215547e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && 215647e946e7SWyllys Ingersoll (hPublicLeafKey == NULL_HKEY)) { 215747e946e7SWyllys Ingersoll /* public session, wrap key with the PRK */ 215847e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 215947e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE; 216047e946e7SWyllys Ingersoll 216147e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) { 216247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 216347e946e7SWyllys Ingersoll } 216447e946e7SWyllys Ingersoll 216547e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 216647e946e7SWyllys Ingersoll } else if (hPrivateLeafKey != NULL_HKEY) { 216747e946e7SWyllys Ingersoll /* logged in USER session */ 216847e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 216947e946e7SWyllys Ingersoll TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; 217047e946e7SWyllys Ingersoll 217147e946e7SWyllys Ingersoll /* get a random SHA1 hash for the auth data */ 217247e946e7SWyllys Ingersoll if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { 217347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 217447e946e7SWyllys Ingersoll } 217547e946e7SWyllys Ingersoll 217647e946e7SWyllys Ingersoll authData = authHash; 217747e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 217847e946e7SWyllys Ingersoll } else { 217947e946e7SWyllys Ingersoll /* logged in SO session */ 218047e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 218147e946e7SWyllys Ingersoll TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; 218247e946e7SWyllys Ingersoll 218347e946e7SWyllys Ingersoll /* get a random SHA1 hash for the auth data */ 218447e946e7SWyllys Ingersoll if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { 218547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 218647e946e7SWyllys Ingersoll } 218747e946e7SWyllys Ingersoll 218847e946e7SWyllys Ingersoll authData = authHash; 218947e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 219047e946e7SWyllys Ingersoll } 219147e946e7SWyllys Ingersoll 219247e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, authData, 219347e946e7SWyllys Ingersoll hParentKey, &hKey))) { 219447e946e7SWyllys Ingersoll return (result); 219547e946e7SWyllys Ingersoll } 219647e946e7SWyllys Ingersoll 219747e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, 219847e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { 219947e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 220047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 220147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 220247e946e7SWyllys Ingersoll } 220347e946e7SWyllys Ingersoll 220447e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, 220547e946e7SWyllys Ingersoll ulBlobLen, &attr))) { 220647e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 220747e946e7SWyllys Ingersoll return (rc); 220847e946e7SWyllys Ingersoll } 220947e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, attr); 221047e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, 221147e946e7SWyllys Ingersoll ulBlobLen, &attr))) { 221247e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 221347e946e7SWyllys Ingersoll return (rc); 221447e946e7SWyllys Ingersoll } 221547e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, attr); 221647e946e7SWyllys Ingersoll 221747e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 221847e946e7SWyllys Ingersoll 221947e946e7SWyllys Ingersoll /* grab the public key to put into the public key object */ 222047e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 222147e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) { 222247e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 222347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 222447e946e7SWyllys Ingersoll return (result); 222547e946e7SWyllys Ingersoll } 222647e946e7SWyllys Ingersoll 222747e946e7SWyllys Ingersoll /* add the public key blob to the object template */ 222847e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { 222947e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 223047e946e7SWyllys Ingersoll return (rc); 223147e946e7SWyllys Ingersoll } 223247e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, attr); 223347e946e7SWyllys Ingersoll 223447e946e7SWyllys Ingersoll /* add the public key blob to the object template */ 223547e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { 223647e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 223747e946e7SWyllys Ingersoll return (rc); 223847e946e7SWyllys Ingersoll } 223947e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, attr); 224047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 224147e946e7SWyllys Ingersoll 224247e946e7SWyllys Ingersoll /* wrap the authdata and put it into an object */ 224347e946e7SWyllys Ingersoll if (authData != NULL) { 224447e946e7SWyllys Ingersoll rc = token_wrap_auth_data(hContext, authData, publ_tmpl, 224547e946e7SWyllys Ingersoll priv_tmpl); 224647e946e7SWyllys Ingersoll } 224747e946e7SWyllys Ingersoll 224847e946e7SWyllys Ingersoll return (rc); 224947e946e7SWyllys Ingersoll } 225047e946e7SWyllys Ingersoll 225147e946e7SWyllys Ingersoll static CK_RV 225247e946e7SWyllys Ingersoll token_rsa_load_key( 225347e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 225447e946e7SWyllys Ingersoll OBJECT *key_obj, 225547e946e7SWyllys Ingersoll TSS_HKEY *phKey) 225647e946e7SWyllys Ingersoll { 225747e946e7SWyllys Ingersoll TSS_RESULT result; 225847e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy = NULL_HPOLICY; 225947e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 226047e946e7SWyllys Ingersoll BYTE *authData = NULL; 226147e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr; 226247e946e7SWyllys Ingersoll CK_RV rc; 226347e946e7SWyllys Ingersoll CK_OBJECT_HANDLE handle; 2264ab8176c2SWyllys Ingersoll CK_ULONG class; 226547e946e7SWyllys Ingersoll 226647e946e7SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 226747e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 226847e946e7SWyllys Ingersoll } else { 226947e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) 227047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 227147e946e7SWyllys Ingersoll 227247e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 227347e946e7SWyllys Ingersoll } 227447e946e7SWyllys Ingersoll 2275ab8176c2SWyllys Ingersoll *phKey = NULL; 2276ab8176c2SWyllys Ingersoll if (template_attribute_find(key_obj->template, CKA_CLASS, 2277ab8176c2SWyllys Ingersoll &attr) == FALSE) { 2278ab8176c2SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 2279ab8176c2SWyllys Ingersoll } 2280ab8176c2SWyllys Ingersoll class = *((CK_ULONG *)attr->pValue); 2281ab8176c2SWyllys Ingersoll 2282ab8176c2SWyllys Ingersoll rc = template_attribute_find(key_obj->template, 2283ab8176c2SWyllys Ingersoll CKA_IBM_OPAQUE, &attr); 2284ab8176c2SWyllys Ingersoll /* 2285ab8176c2SWyllys Ingersoll * A public key cannot use the OPAQUE data attribute so they 2286ab8176c2SWyllys Ingersoll * must be created in software. A private key may not yet 2287ab8176c2SWyllys Ingersoll * have its "opaque" data defined and needs to be created 2288ab8176c2SWyllys Ingersoll * and loaded so it can be used inside the TPM. 2289ab8176c2SWyllys Ingersoll */ 2290ab8176c2SWyllys Ingersoll if (class == CKO_PUBLIC_KEY || rc == FALSE) { 229147e946e7SWyllys Ingersoll rc = object_mgr_find_in_map2(hContext, key_obj, &handle); 229247e946e7SWyllys Ingersoll if (rc != CKR_OK) 229347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 229447e946e7SWyllys Ingersoll 229547e946e7SWyllys Ingersoll if ((rc = token_load_key(hContext, 229647e946e7SWyllys Ingersoll handle, hParentKey, NULL, phKey))) { 229747e946e7SWyllys Ingersoll return (rc); 229847e946e7SWyllys Ingersoll } 2299ab8176c2SWyllys Ingersoll } 2300ab8176c2SWyllys Ingersoll /* 2301ab8176c2SWyllys Ingersoll * If this is a private key, get the blob and load it in the TPM. 2302ab8176c2SWyllys Ingersoll * If it is public, the key is already loaded in software. 2303ab8176c2SWyllys Ingersoll */ 2304ab8176c2SWyllys Ingersoll if (class == CKO_PRIVATE_KEY) { 2305ab8176c2SWyllys Ingersoll /* If we already have a handle, just load it */ 2306ab8176c2SWyllys Ingersoll if (*phKey != NULL) { 2307ab8176c2SWyllys Ingersoll result = Tspi_Key_LoadKey(*phKey, hParentKey); 2308ab8176c2SWyllys Ingersoll if (result) { 2309ab8176c2SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByBlob: " 2310ab8176c2SWyllys Ingersoll "0x%0x - %s", 2311ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 2312ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 2313ab8176c2SWyllys Ingersoll } 2314ab8176c2SWyllys Ingersoll } else { 231547e946e7SWyllys Ingersoll /* try again to get the CKA_IBM_OPAQUE attr */ 231647e946e7SWyllys Ingersoll if ((rc = template_attribute_find(key_obj->template, 231747e946e7SWyllys Ingersoll CKA_IBM_OPAQUE, &attr)) == FALSE) { 231847e946e7SWyllys Ingersoll return (rc); 231947e946e7SWyllys Ingersoll } 232047e946e7SWyllys Ingersoll if ((result = Tspi_Context_LoadKeyByBlob(hContext, 2321ab8176c2SWyllys Ingersoll hParentKey, attr->ulValueLen, attr->pValue, 2322ab8176c2SWyllys Ingersoll phKey))) { 2323ab8176c2SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByBlob: " 2324ab8176c2SWyllys Ingersoll "0x%0x - %s", 232547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 232647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 232747e946e7SWyllys Ingersoll } 2328ab8176c2SWyllys Ingersoll } 2329ab8176c2SWyllys Ingersoll } 233047e946e7SWyllys Ingersoll 233147e946e7SWyllys Ingersoll /* auth data may be required */ 233247e946e7SWyllys Ingersoll if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA, 233347e946e7SWyllys Ingersoll &attr) == TRUE && attr) { 233447e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && 233547e946e7SWyllys Ingersoll (hPublicLeafKey == NULL_HKEY)) { 233647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 233747e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 233847e946e7SWyllys Ingersoll hParentKey = hPublicLeafKey; 233947e946e7SWyllys Ingersoll } else { 234047e946e7SWyllys Ingersoll hParentKey = hPrivateLeafKey; 234147e946e7SWyllys Ingersoll } 234247e946e7SWyllys Ingersoll 234347e946e7SWyllys Ingersoll if ((result = token_unwrap_auth_data(hContext, 2344ab8176c2SWyllys Ingersoll attr->pValue, attr->ulValueLen, 2345ab8176c2SWyllys Ingersoll hParentKey, &authData))) { 234647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 234747e946e7SWyllys Ingersoll } 234847e946e7SWyllys Ingersoll 234947e946e7SWyllys Ingersoll if ((result = Tspi_GetPolicyObject(*phKey, 235047e946e7SWyllys Ingersoll TSS_POLICY_USAGE, &hPolicy))) { 235147e946e7SWyllys Ingersoll stlogit("Tspi_GetPolicyObject: 0x%0x - %s", 235247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 235347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 235447e946e7SWyllys Ingersoll } 235547e946e7SWyllys Ingersoll 235647e946e7SWyllys Ingersoll /* 235747e946e7SWyllys Ingersoll * If the policy handle returned is the same as the 235847e946e7SWyllys Ingersoll * context's default policy, then a new policy must 235947e946e7SWyllys Ingersoll * be created and assigned to the key. Otherwise, just set the 236047e946e7SWyllys Ingersoll * secret in the policy. 236147e946e7SWyllys Ingersoll */ 236247e946e7SWyllys Ingersoll if (hPolicy == hDefaultPolicy) { 236347e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 236447e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 236547e946e7SWyllys Ingersoll &hPolicy))) { 236647e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: " 236747e946e7SWyllys Ingersoll "0x%0x - %s", 236847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 236947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 237047e946e7SWyllys Ingersoll } 237147e946e7SWyllys Ingersoll 237247e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, 237347e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, 237447e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, authData))) { 237547e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: " 237647e946e7SWyllys Ingersoll "0x%0x - %s", 237747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 237847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 237947e946e7SWyllys Ingersoll } 238047e946e7SWyllys Ingersoll 238147e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hPolicy, 238247e946e7SWyllys Ingersoll *phKey))) { 238347e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: " 238447e946e7SWyllys Ingersoll "0x%0x - %s", 238547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 238647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 238747e946e7SWyllys Ingersoll } 238847e946e7SWyllys Ingersoll } else if ((result = Tspi_Policy_SetSecret(hPolicy, 238947e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) { 239047e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 239147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 239247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 239347e946e7SWyllys Ingersoll } 239447e946e7SWyllys Ingersoll 239547e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, authData); 239647e946e7SWyllys Ingersoll } 239747e946e7SWyllys Ingersoll 239847e946e7SWyllys Ingersoll return (CKR_OK); 239947e946e7SWyllys Ingersoll } 240047e946e7SWyllys Ingersoll 240147e946e7SWyllys Ingersoll CK_RV 240247e946e7SWyllys Ingersoll tpm_decrypt_data( 240347e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 240447e946e7SWyllys Ingersoll TSS_HKEY hKey, 240547e946e7SWyllys Ingersoll CK_BYTE * in_data, 240647e946e7SWyllys Ingersoll CK_ULONG in_data_len, 240747e946e7SWyllys Ingersoll CK_BYTE * out_data, 240847e946e7SWyllys Ingersoll CK_ULONG * out_data_len) 240947e946e7SWyllys Ingersoll { 241047e946e7SWyllys Ingersoll TSS_RESULT result; 241147e946e7SWyllys Ingersoll TSS_HENCDATA hEncData = NULL_HENCDATA; 241247e946e7SWyllys Ingersoll UINT32 buf_size = 0, modLen; 241347e946e7SWyllys Ingersoll BYTE *buf = NULL, *modulus = NULL; 241447e946e7SWyllys Ingersoll CK_ULONG chunklen, remain, outlen; 241547e946e7SWyllys Ingersoll 241647e946e7SWyllys Ingersoll /* push the data into the encrypted data object */ 241747e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 241847e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 241947e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 242047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 242147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 242247e946e7SWyllys Ingersoll } 242347e946e7SWyllys Ingersoll 242447e946e7SWyllys Ingersoll /* 242547e946e7SWyllys Ingersoll * Figure out the modulus size so we can break the data 242647e946e7SWyllys Ingersoll * into smaller chunks if necessary. 242747e946e7SWyllys Ingersoll */ 242847e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 242947e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 243047e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 243147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 243247e946e7SWyllys Ingersoll return (result); 243347e946e7SWyllys Ingersoll } 243447e946e7SWyllys Ingersoll /* we don't need the actual modulus */ 243547e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 243647e946e7SWyllys Ingersoll 243747e946e7SWyllys Ingersoll chunklen = (in_data_len > modLen ? modLen : in_data_len); 243847e946e7SWyllys Ingersoll remain = in_data_len; 243947e946e7SWyllys Ingersoll outlen = 0; 244047e946e7SWyllys Ingersoll 244147e946e7SWyllys Ingersoll while (remain > 0) { 244247e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribData(hEncData, 244347e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, 244447e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, 244547e946e7SWyllys Ingersoll chunklen, in_data))) { 244647e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 244747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 244847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 244947e946e7SWyllys Ingersoll } 245047e946e7SWyllys Ingersoll 245147e946e7SWyllys Ingersoll /* unbind the data, receiving the plaintext back */ 245247e946e7SWyllys Ingersoll if ((result = Tspi_Data_Unbind(hEncData, hKey, 245347e946e7SWyllys Ingersoll &buf_size, &buf))) { 245447e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 245547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 245647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 245747e946e7SWyllys Ingersoll } 245847e946e7SWyllys Ingersoll 245947e946e7SWyllys Ingersoll if (*out_data_len < buf_size + outlen) { 246047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, buf); 246147e946e7SWyllys Ingersoll return (CKR_BUFFER_TOO_SMALL); 246247e946e7SWyllys Ingersoll } 246347e946e7SWyllys Ingersoll 246447e946e7SWyllys Ingersoll (void) memcpy(out_data + outlen, buf, buf_size); 246547e946e7SWyllys Ingersoll 246647e946e7SWyllys Ingersoll outlen += buf_size; 246747e946e7SWyllys Ingersoll in_data += chunklen; 246847e946e7SWyllys Ingersoll remain -= chunklen; 246947e946e7SWyllys Ingersoll 247047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, buf); 247147e946e7SWyllys Ingersoll if (chunklen > remain) 247247e946e7SWyllys Ingersoll chunklen = remain; 247347e946e7SWyllys Ingersoll } 247447e946e7SWyllys Ingersoll *out_data_len = outlen; 247547e946e7SWyllys Ingersoll return (CKR_OK); 247647e946e7SWyllys Ingersoll } 247747e946e7SWyllys Ingersoll 247847e946e7SWyllys Ingersoll CK_RV 247947e946e7SWyllys Ingersoll token_specific_rsa_decrypt( 248047e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 248147e946e7SWyllys Ingersoll CK_BYTE * in_data, 248247e946e7SWyllys Ingersoll CK_ULONG in_data_len, 248347e946e7SWyllys Ingersoll CK_BYTE * out_data, 248447e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 248547e946e7SWyllys Ingersoll OBJECT * key_obj) 248647e946e7SWyllys Ingersoll { 248747e946e7SWyllys Ingersoll CK_RV rc; 248847e946e7SWyllys Ingersoll TSS_HKEY hKey; 248947e946e7SWyllys Ingersoll 249047e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 249147e946e7SWyllys Ingersoll return (rc); 249247e946e7SWyllys Ingersoll } 249347e946e7SWyllys Ingersoll 249447e946e7SWyllys Ingersoll rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len, 249547e946e7SWyllys Ingersoll out_data, out_data_len); 249647e946e7SWyllys Ingersoll 249747e946e7SWyllys Ingersoll return (rc); 249847e946e7SWyllys Ingersoll } 249947e946e7SWyllys Ingersoll 250047e946e7SWyllys Ingersoll CK_RV 250147e946e7SWyllys Ingersoll token_specific_rsa_verify( 250247e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 250347e946e7SWyllys Ingersoll CK_BYTE * in_data, 250447e946e7SWyllys Ingersoll CK_ULONG in_data_len, 250547e946e7SWyllys Ingersoll CK_BYTE * sig, 250647e946e7SWyllys Ingersoll CK_ULONG sig_len, 250747e946e7SWyllys Ingersoll OBJECT * key_obj) 250847e946e7SWyllys Ingersoll { 250947e946e7SWyllys Ingersoll TSS_RESULT result; 251047e946e7SWyllys Ingersoll TSS_HHASH hHash; 251147e946e7SWyllys Ingersoll TSS_HKEY hKey; 251247e946e7SWyllys Ingersoll CK_RV rc; 251347e946e7SWyllys Ingersoll 251447e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 251547e946e7SWyllys Ingersoll return (rc); 251647e946e7SWyllys Ingersoll } 251747e946e7SWyllys Ingersoll 251847e946e7SWyllys Ingersoll /* Create the hash object we'll use to sign */ 251947e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 252047e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { 252147e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 252247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 252347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 252447e946e7SWyllys Ingersoll } 252547e946e7SWyllys Ingersoll 252647e946e7SWyllys Ingersoll /* Insert the data into the hash object */ 252747e946e7SWyllys Ingersoll if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, 252847e946e7SWyllys Ingersoll in_data))) { 252947e946e7SWyllys Ingersoll stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", 253047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 253147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 253247e946e7SWyllys Ingersoll } 253347e946e7SWyllys Ingersoll 253447e946e7SWyllys Ingersoll /* Verify */ 253547e946e7SWyllys Ingersoll result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig); 253647e946e7SWyllys Ingersoll if (result != TSS_SUCCESS && 253747e946e7SWyllys Ingersoll TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) { 253847e946e7SWyllys Ingersoll stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s", 253947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 254047e946e7SWyllys Ingersoll } 254147e946e7SWyllys Ingersoll 254247e946e7SWyllys Ingersoll if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) { 254347e946e7SWyllys Ingersoll rc = CKR_SIGNATURE_INVALID; 254447e946e7SWyllys Ingersoll } else { 254547e946e7SWyllys Ingersoll rc = CKR_OK; 254647e946e7SWyllys Ingersoll } 254747e946e7SWyllys Ingersoll 254847e946e7SWyllys Ingersoll return (rc); 254947e946e7SWyllys Ingersoll } 255047e946e7SWyllys Ingersoll 255147e946e7SWyllys Ingersoll CK_RV 255247e946e7SWyllys Ingersoll token_specific_rsa_sign( 255347e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 255447e946e7SWyllys Ingersoll CK_BYTE * in_data, 255547e946e7SWyllys Ingersoll CK_ULONG in_data_len, 255647e946e7SWyllys Ingersoll CK_BYTE * out_data, 255747e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 255847e946e7SWyllys Ingersoll OBJECT * key_obj) 255947e946e7SWyllys Ingersoll { 256047e946e7SWyllys Ingersoll TSS_RESULT result; 256147e946e7SWyllys Ingersoll TSS_HHASH hHash; 256247e946e7SWyllys Ingersoll BYTE *sig; 256347e946e7SWyllys Ingersoll UINT32 sig_len; 256447e946e7SWyllys Ingersoll TSS_HKEY hKey; 256547e946e7SWyllys Ingersoll CK_RV rc; 256647e946e7SWyllys Ingersoll 256747e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 256847e946e7SWyllys Ingersoll return (rc); 256947e946e7SWyllys Ingersoll } 257047e946e7SWyllys Ingersoll 257147e946e7SWyllys Ingersoll /* Create the hash object we'll use to sign */ 257247e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 257347e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { 257447e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 257547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 257647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 257747e946e7SWyllys Ingersoll } 257847e946e7SWyllys Ingersoll 257947e946e7SWyllys Ingersoll /* Insert the data into the hash object */ 258047e946e7SWyllys Ingersoll if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, 258147e946e7SWyllys Ingersoll in_data))) { 258247e946e7SWyllys Ingersoll stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", 258347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 258447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 258547e946e7SWyllys Ingersoll } 258647e946e7SWyllys Ingersoll 258747e946e7SWyllys Ingersoll /* Sign */ 258847e946e7SWyllys Ingersoll if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) { 258947e946e7SWyllys Ingersoll stlogit("Tspi_Hash_Sign: 0x%0x - %s", 259047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 2591ab8176c2SWyllys Ingersoll return (CKR_DATA_LEN_RANGE); 259247e946e7SWyllys Ingersoll } 259347e946e7SWyllys Ingersoll 259447e946e7SWyllys Ingersoll if (sig_len > *out_data_len) { 259547e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, sig); 259647e946e7SWyllys Ingersoll return (CKR_BUFFER_TOO_SMALL); 259747e946e7SWyllys Ingersoll } 259847e946e7SWyllys Ingersoll 259947e946e7SWyllys Ingersoll (void) memcpy(out_data, sig, sig_len); 260047e946e7SWyllys Ingersoll *out_data_len = sig_len; 260147e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, sig); 260247e946e7SWyllys Ingersoll 260347e946e7SWyllys Ingersoll return (CKR_OK); 260447e946e7SWyllys Ingersoll } 260547e946e7SWyllys Ingersoll 260647e946e7SWyllys Ingersoll CK_RV 260747e946e7SWyllys Ingersoll tpm_encrypt_data( 260847e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 260947e946e7SWyllys Ingersoll TSS_HKEY hKey, 261047e946e7SWyllys Ingersoll CK_BYTE *in_data, 261147e946e7SWyllys Ingersoll CK_ULONG in_data_len, 261247e946e7SWyllys Ingersoll CK_BYTE *out_data, 261347e946e7SWyllys Ingersoll CK_ULONG *out_data_len) 261447e946e7SWyllys Ingersoll { 261547e946e7SWyllys Ingersoll TSS_RESULT result; 261647e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 261747e946e7SWyllys Ingersoll BYTE *dataBlob, *modulus; 261847e946e7SWyllys Ingersoll UINT32 dataBlobSize, modLen; 261947e946e7SWyllys Ingersoll CK_ULONG chunklen, remain; 262047e946e7SWyllys Ingersoll CK_ULONG outlen; 2621ab8176c2SWyllys Ingersoll UINT32 keyusage, scheme, maxsize; 262247e946e7SWyllys Ingersoll 262347e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 262447e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 262547e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 262647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 262747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 262847e946e7SWyllys Ingersoll } 262947e946e7SWyllys Ingersoll /* 263047e946e7SWyllys Ingersoll * Figure out the modulus size so we can break the data 263147e946e7SWyllys Ingersoll * into smaller chunks if necessary. 263247e946e7SWyllys Ingersoll */ 263347e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 263447e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 263547e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 263647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 263747e946e7SWyllys Ingersoll return (result); 263847e946e7SWyllys Ingersoll } 263947e946e7SWyllys Ingersoll /* we don't need the actual modulus */ 264047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 264147e946e7SWyllys Ingersoll 264247e946e7SWyllys Ingersoll /* 264347e946e7SWyllys Ingersoll * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5), 2644ab8176c2SWyllys Ingersoll * Max input data size varies depending on the key type and 2645ab8176c2SWyllys Ingersoll * encryption scheme. 264647e946e7SWyllys Ingersoll */ 2647ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, 2648ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_USAGE, &keyusage))) { 2649ab8176c2SWyllys Ingersoll stlogit("Cannot find USAGE: %s\n", 2650ab8176c2SWyllys Ingersoll Trspi_Error_String(result)); 2651ab8176c2SWyllys Ingersoll return (result); 2652ab8176c2SWyllys Ingersoll } 2653ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, 2654ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &scheme))) { 2655ab8176c2SWyllys Ingersoll stlogit("Cannot find ENCSCHEME: %s\n", 2656ab8176c2SWyllys Ingersoll Trspi_Error_String(result)); 2657ab8176c2SWyllys Ingersoll return (result); 2658ab8176c2SWyllys Ingersoll } 2659ab8176c2SWyllys Ingersoll switch (scheme) { 2660ab8176c2SWyllys Ingersoll case TSS_ES_RSAESPKCSV15: 2661ab8176c2SWyllys Ingersoll if (keyusage == TSS_KEYUSAGE_BIND) 2662ab8176c2SWyllys Ingersoll maxsize = 16; 2663ab8176c2SWyllys Ingersoll else /* legacy */ 2664ab8176c2SWyllys Ingersoll maxsize = 11; 2665ab8176c2SWyllys Ingersoll break; 2666ab8176c2SWyllys Ingersoll case TSS_ES_RSAESOAEP_SHA1_MGF1: 2667ab8176c2SWyllys Ingersoll maxsize = 47; 2668ab8176c2SWyllys Ingersoll break; 2669ab8176c2SWyllys Ingersoll default: 2670ab8176c2SWyllys Ingersoll maxsize = 0; 2671ab8176c2SWyllys Ingersoll } 2672ab8176c2SWyllys Ingersoll 2673ab8176c2SWyllys Ingersoll modLen -= maxsize; 267447e946e7SWyllys Ingersoll 267547e946e7SWyllys Ingersoll chunklen = (in_data_len > modLen ? modLen : in_data_len); 267647e946e7SWyllys Ingersoll remain = in_data_len; 267747e946e7SWyllys Ingersoll outlen = 0; 267847e946e7SWyllys Ingersoll while (remain > 0) { 267947e946e7SWyllys Ingersoll if ((result = Tspi_Data_Bind(hEncData, hKey, 268047e946e7SWyllys Ingersoll chunklen, in_data))) { 268147e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 268247e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 268347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 268447e946e7SWyllys Ingersoll } 268547e946e7SWyllys Ingersoll 268647e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hEncData, 268747e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, 268847e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, 268947e946e7SWyllys Ingersoll &dataBlobSize, &dataBlob))) { 269047e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 269147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 269247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 269347e946e7SWyllys Ingersoll } 269447e946e7SWyllys Ingersoll 269547e946e7SWyllys Ingersoll if (outlen + dataBlobSize > *out_data_len) { 269647e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, dataBlob); 269747e946e7SWyllys Ingersoll return (CKR_DATA_LEN_RANGE); 269847e946e7SWyllys Ingersoll } 269947e946e7SWyllys Ingersoll 270047e946e7SWyllys Ingersoll (void) memcpy(out_data + outlen, 270147e946e7SWyllys Ingersoll dataBlob, dataBlobSize); 270247e946e7SWyllys Ingersoll 270347e946e7SWyllys Ingersoll outlen += dataBlobSize; 270447e946e7SWyllys Ingersoll in_data += chunklen; 270547e946e7SWyllys Ingersoll remain -= chunklen; 270647e946e7SWyllys Ingersoll 270747e946e7SWyllys Ingersoll if (chunklen > remain) 270847e946e7SWyllys Ingersoll chunklen = remain; 270947e946e7SWyllys Ingersoll 271047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, dataBlob); 271147e946e7SWyllys Ingersoll } 271247e946e7SWyllys Ingersoll *out_data_len = outlen; 271347e946e7SWyllys Ingersoll 271447e946e7SWyllys Ingersoll return (CKR_OK); 271547e946e7SWyllys Ingersoll } 271647e946e7SWyllys Ingersoll 271747e946e7SWyllys Ingersoll CK_RV 271847e946e7SWyllys Ingersoll token_specific_rsa_encrypt( 271947e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 272047e946e7SWyllys Ingersoll CK_BYTE * in_data, 272147e946e7SWyllys Ingersoll CK_ULONG in_data_len, 272247e946e7SWyllys Ingersoll CK_BYTE * out_data, 272347e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 272447e946e7SWyllys Ingersoll OBJECT * key_obj) 272547e946e7SWyllys Ingersoll { 272647e946e7SWyllys Ingersoll TSS_HKEY hKey; 272747e946e7SWyllys Ingersoll CK_RV rc; 272847e946e7SWyllys Ingersoll 272947e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 273047e946e7SWyllys Ingersoll return (rc); 273147e946e7SWyllys Ingersoll } 273247e946e7SWyllys Ingersoll 273347e946e7SWyllys Ingersoll rc = tpm_encrypt_data(hContext, hKey, in_data, in_data_len, 273447e946e7SWyllys Ingersoll out_data, out_data_len); 273547e946e7SWyllys Ingersoll 273647e946e7SWyllys Ingersoll return (rc); 273747e946e7SWyllys Ingersoll } 2738ab8176c2SWyllys Ingersoll 2739ab8176c2SWyllys Ingersoll /* 2740ab8176c2SWyllys Ingersoll * RSA Verify Recover 2741ab8176c2SWyllys Ingersoll * 2742ab8176c2SWyllys Ingersoll * Public key crypto is done in software, not by the TPM. 2743ab8176c2SWyllys Ingersoll * We bypass the TSPI library here in favor of calls directly 2744ab8176c2SWyllys Ingersoll * to OpenSSL because we don't want to add any padding, the in_data (signature) 2745ab8176c2SWyllys Ingersoll * already contains the data stream to be decrypted and is already 2746ab8176c2SWyllys Ingersoll * padded and formatted correctly. 2747ab8176c2SWyllys Ingersoll */ 2748ab8176c2SWyllys Ingersoll CK_RV 2749ab8176c2SWyllys Ingersoll token_specific_rsa_verify_recover( 2750ab8176c2SWyllys Ingersoll TSS_HCONTEXT hContext, 2751ab8176c2SWyllys Ingersoll CK_BYTE *in_data, /* signature */ 2752ab8176c2SWyllys Ingersoll CK_ULONG in_data_len, 2753ab8176c2SWyllys Ingersoll CK_BYTE *out_data, /* decrypted */ 2754ab8176c2SWyllys Ingersoll CK_ULONG *out_data_len, 2755ab8176c2SWyllys Ingersoll OBJECT *key_obj) 2756ab8176c2SWyllys Ingersoll { 2757ab8176c2SWyllys Ingersoll TSS_HKEY hKey; 2758ab8176c2SWyllys Ingersoll TSS_RESULT result; 2759ab8176c2SWyllys Ingersoll CK_RV rc; 2760ab8176c2SWyllys Ingersoll BYTE *modulus; 2761ab8176c2SWyllys Ingersoll UINT32 modLen; 2762ab8176c2SWyllys Ingersoll RSA *rsa = NULL; 2763ab8176c2SWyllys Ingersoll uchar_t exp[] = { 0x01, 0x00, 0x01 }; 2764ab8176c2SWyllys Ingersoll int sslrv, num; 2765ab8176c2SWyllys Ingersoll BYTE temp[MAX_RSA_KEYLENGTH]; 2766*1dc1cb45SWyllys Ingersoll BYTE outdata[MAX_RSA_KEYLENGTH]; 2767ab8176c2SWyllys Ingersoll int i; 2768ab8176c2SWyllys Ingersoll 2769ab8176c2SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 2770ab8176c2SWyllys Ingersoll return (rc); 2771ab8176c2SWyllys Ingersoll } 2772ab8176c2SWyllys Ingersoll 2773ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 2774ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 2775ab8176c2SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 2776ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 2777ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 2778ab8176c2SWyllys Ingersoll } 2779ab8176c2SWyllys Ingersoll 2780ab8176c2SWyllys Ingersoll if (in_data_len != modLen) { 2781ab8176c2SWyllys Ingersoll rc = CKR_SIGNATURE_LEN_RANGE; 2782ab8176c2SWyllys Ingersoll goto end; 2783ab8176c2SWyllys Ingersoll } 2784ab8176c2SWyllys Ingersoll 2785ab8176c2SWyllys Ingersoll rsa = RSA_new(); 2786ab8176c2SWyllys Ingersoll if (rsa == NULL) { 2787ab8176c2SWyllys Ingersoll rc = CKR_HOST_MEMORY; 2788ab8176c2SWyllys Ingersoll goto end; 2789ab8176c2SWyllys Ingersoll } 2790ab8176c2SWyllys Ingersoll 2791ab8176c2SWyllys Ingersoll rsa->n = BN_bin2bn(modulus, modLen, rsa->n); 2792ab8176c2SWyllys Ingersoll rsa->e = BN_bin2bn(exp, sizeof (exp), rsa->e); 2793ab8176c2SWyllys Ingersoll if (rsa->n == NULL || rsa->e == NULL) { 2794ab8176c2SWyllys Ingersoll rc = CKR_HOST_MEMORY; 2795ab8176c2SWyllys Ingersoll goto end; 2796ab8176c2SWyllys Ingersoll } 2797ab8176c2SWyllys Ingersoll 2798*1dc1cb45SWyllys Ingersoll rsa->flags |= RSA_FLAG_SIGN_VER; 2799*1dc1cb45SWyllys Ingersoll 2800ab8176c2SWyllys Ingersoll /* use RSA_NO_PADDING because the data is already padded (PKCS1) */ 2801*1dc1cb45SWyllys Ingersoll sslrv = RSA_public_encrypt(in_data_len, in_data, outdata, 2802ab8176c2SWyllys Ingersoll rsa, RSA_NO_PADDING); 2803ab8176c2SWyllys Ingersoll if (sslrv == -1) { 2804ab8176c2SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 2805ab8176c2SWyllys Ingersoll goto end; 2806ab8176c2SWyllys Ingersoll } 2807ab8176c2SWyllys Ingersoll 2808ab8176c2SWyllys Ingersoll /* Strip leading 0's before stripping the padding */ 2809ab8176c2SWyllys Ingersoll for (i = 0; i < sslrv; i++) 2810*1dc1cb45SWyllys Ingersoll if (outdata[i] != 0) 2811ab8176c2SWyllys Ingersoll break; 2812ab8176c2SWyllys Ingersoll 2813ab8176c2SWyllys Ingersoll num = BN_num_bytes(rsa->n); 2814ab8176c2SWyllys Ingersoll 2815ab8176c2SWyllys Ingersoll /* Use OpenSSL function for stripping PKCS#1 padding */ 2816ab8176c2SWyllys Ingersoll sslrv = RSA_padding_check_PKCS1_type_1(temp, sizeof (temp), 2817*1dc1cb45SWyllys Ingersoll &outdata[i], sslrv - i, num); 2818ab8176c2SWyllys Ingersoll 2819ab8176c2SWyllys Ingersoll if (sslrv < 0) { 2820ab8176c2SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 2821ab8176c2SWyllys Ingersoll goto end; 2822ab8176c2SWyllys Ingersoll } 2823ab8176c2SWyllys Ingersoll 2824ab8176c2SWyllys Ingersoll if (*out_data_len < sslrv) { 2825ab8176c2SWyllys Ingersoll rc = CKR_BUFFER_TOO_SMALL; 2826ab8176c2SWyllys Ingersoll *out_data_len = 0; 2827ab8176c2SWyllys Ingersoll goto end; 2828ab8176c2SWyllys Ingersoll } 2829ab8176c2SWyllys Ingersoll 2830ab8176c2SWyllys Ingersoll /* The return code indicates the number of bytes remaining */ 2831ab8176c2SWyllys Ingersoll (void) memcpy(out_data, temp, sslrv); 2832ab8176c2SWyllys Ingersoll *out_data_len = sslrv; 2833ab8176c2SWyllys Ingersoll end: 2834ab8176c2SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 2835ab8176c2SWyllys Ingersoll if (rsa) 2836ab8176c2SWyllys Ingersoll RSA_free(rsa); 2837ab8176c2SWyllys Ingersoll 2838ab8176c2SWyllys Ingersoll return (rc); 2839ab8176c2SWyllys Ingersoll } 2840