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 37*ab8176c2SWyllys Ingersoll #include <openssl/rsa.h> 38*ab8176c2SWyllys 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 51*ab8176c2SWyllys Ingersoll #define MAX_RSA_KEYLENGTH 512 52*ab8176c2SWyllys 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); 58*ab8176c2SWyllys 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 168*ab8176c2SWyllys Ingersoll static TSS_RESULT 169*ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT, TSS_FLAG, TSS_HKEY, CK_CHAR *); 170*ab8176c2SWyllys Ingersoll 171*ab8176c2SWyllys Ingersoll static TSS_RESULT 172*ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY); 173*ab8176c2SWyllys 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 56947e946e7SWyllys Ingersoll (void) memcpy(&tpmvinfo, (void *)data, sizeof (tpmvinfo)); 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); 57647e946e7SWyllys Ingersoll (void) memcpy(td->token_info.manufacturerID, 57747e946e7SWyllys Ingersoll tpmvinfo.tpmVendorID, sizeof (tpmvinfo.tpmVendorID)); 57847e946e7SWyllys Ingersoll 57947e946e7SWyllys Ingersoll (void) memset(td->token_info.label, ' ', 58047e946e7SWyllys Ingersoll sizeof (td->token_info.label) - 1); 58147e946e7SWyllys Ingersoll (void) memcpy(td->token_info.label, "TPM", 6); 58247e946e7SWyllys Ingersoll 58347e946e7SWyllys Ingersoll td->token_info.hardwareVersion.major = tpmvinfo.version.major; 58447e946e7SWyllys Ingersoll td->token_info.hardwareVersion.minor = tpmvinfo.version.minor; 58547e946e7SWyllys Ingersoll td->token_info.firmwareVersion.major = tpmvinfo.version.revMajor; 58647e946e7SWyllys Ingersoll td->token_info.firmwareVersion.minor = tpmvinfo.version.revMinor; 58747e946e7SWyllys Ingersoll 58847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, data); 58947e946e7SWyllys Ingersoll return (CKR_OK); 59047e946e7SWyllys Ingersoll } 59147e946e7SWyllys Ingersoll 59247e946e7SWyllys Ingersoll /*ARGSUSED*/ 59347e946e7SWyllys Ingersoll CK_RV 59447e946e7SWyllys Ingersoll token_specific_session(CK_SLOT_ID slotid) 59547e946e7SWyllys Ingersoll { 59647e946e7SWyllys Ingersoll return (CKR_OK); 59747e946e7SWyllys Ingersoll } 59847e946e7SWyllys Ingersoll 59947e946e7SWyllys Ingersoll CK_RV 60047e946e7SWyllys Ingersoll token_rng(TSS_HCONTEXT hContext, CK_BYTE *output, CK_ULONG bytes) 60147e946e7SWyllys Ingersoll { 60247e946e7SWyllys Ingersoll TSS_RESULT rc; 60347e946e7SWyllys Ingersoll TSS_HTPM hTPM; 60447e946e7SWyllys Ingersoll BYTE *random_bytes = NULL; 60547e946e7SWyllys Ingersoll 60647e946e7SWyllys Ingersoll if ((rc = Tspi_Context_GetTpmObject(hContext, &hTPM))) { 60747e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", 60847e946e7SWyllys Ingersoll rc, Trspi_Error_String(rc)); 60947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 61047e946e7SWyllys Ingersoll } 61147e946e7SWyllys Ingersoll 61247e946e7SWyllys Ingersoll if ((rc = Tspi_TPM_GetRandom(hTPM, bytes, &random_bytes))) { 61347e946e7SWyllys Ingersoll stlogit("Tspi_TPM_GetRandom: 0x%0x - %s", 61447e946e7SWyllys Ingersoll rc, Trspi_Error_String(rc)); 61547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 61647e946e7SWyllys Ingersoll } 61747e946e7SWyllys Ingersoll 61847e946e7SWyllys Ingersoll (void) memcpy(output, random_bytes, bytes); 61947e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, random_bytes); 62047e946e7SWyllys Ingersoll 62147e946e7SWyllys Ingersoll return (CKR_OK); 62247e946e7SWyllys Ingersoll } 62347e946e7SWyllys Ingersoll 62447e946e7SWyllys Ingersoll TSS_RESULT 62547e946e7SWyllys Ingersoll open_tss_context(TSS_HCONTEXT *pContext) 62647e946e7SWyllys Ingersoll { 62747e946e7SWyllys Ingersoll TSS_RESULT result; 62847e946e7SWyllys Ingersoll 62947e946e7SWyllys Ingersoll if ((result = Tspi_Context_Create(pContext))) { 63047e946e7SWyllys Ingersoll stlogit("Tspi_Context_Create: 0x%0x - %s", 63147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 63247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 63347e946e7SWyllys Ingersoll } 63447e946e7SWyllys Ingersoll 63547e946e7SWyllys Ingersoll if ((result = Tspi_Context_Connect(*pContext, NULL))) { 63647e946e7SWyllys Ingersoll stlogit("Tspi_Context_Connect: 0x%0x - %s", 63747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 63847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 63947e946e7SWyllys Ingersoll } 64047e946e7SWyllys Ingersoll return (result); 64147e946e7SWyllys Ingersoll } 64247e946e7SWyllys Ingersoll 64347e946e7SWyllys Ingersoll /*ARGSUSED*/ 64447e946e7SWyllys Ingersoll static CK_RV 64547e946e7SWyllys Ingersoll token_specific_init(char *Correlator, CK_SLOT_ID SlotNumber, 64647e946e7SWyllys Ingersoll TSS_HCONTEXT *hContext) 64747e946e7SWyllys Ingersoll { 64847e946e7SWyllys Ingersoll TSS_RESULT result; 64947e946e7SWyllys Ingersoll 65047e946e7SWyllys Ingersoll result = open_tss_context(hContext); 65147e946e7SWyllys Ingersoll if (result) 65247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 65347e946e7SWyllys Ingersoll 65447e946e7SWyllys Ingersoll if ((result = Tspi_Context_GetDefaultPolicy(*hContext, 65547e946e7SWyllys Ingersoll &hDefaultPolicy))) { 65647e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetDefaultPolicy: 0x%0x - %s", 65747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 65847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 65947e946e7SWyllys Ingersoll } 66047e946e7SWyllys Ingersoll 66147e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 66247e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 66347e946e7SWyllys Ingersoll local_uuid_clear(&publicLeafKeyUUID); 66447e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 66547e946e7SWyllys Ingersoll 66647e946e7SWyllys Ingersoll result = token_get_tpm_info(*hContext, nv_token_data); 66747e946e7SWyllys Ingersoll return (result); 66847e946e7SWyllys Ingersoll } 66947e946e7SWyllys Ingersoll 67047e946e7SWyllys Ingersoll /* 67147e946e7SWyllys Ingersoll * Given a modulus and prime from an RSA key, create a TSS_HKEY object by 67247e946e7SWyllys Ingersoll * wrapping the RSA key with a key from the TPM (SRK or other previously stored 67347e946e7SWyllys Ingersoll * key). 67447e946e7SWyllys Ingersoll */ 67547e946e7SWyllys Ingersoll static CK_RV 67647e946e7SWyllys Ingersoll token_wrap_sw_key( 67747e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 67847e946e7SWyllys Ingersoll int size_n, 67947e946e7SWyllys Ingersoll unsigned char *n, 68047e946e7SWyllys Ingersoll int size_p, 68147e946e7SWyllys Ingersoll unsigned char *p, 68247e946e7SWyllys Ingersoll TSS_HKEY hParentKey, 68347e946e7SWyllys Ingersoll TSS_FLAG initFlags, 68447e946e7SWyllys Ingersoll TSS_HKEY *phKey) 68547e946e7SWyllys Ingersoll { 68647e946e7SWyllys Ingersoll TSS_RESULT result; 68747e946e7SWyllys Ingersoll UINT32 key_size; 68847e946e7SWyllys Ingersoll 68947e946e7SWyllys Ingersoll key_size = util_get_keysize_flag(size_n * 8); 69047e946e7SWyllys Ingersoll if (initFlags == 0) { 69147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 69247e946e7SWyllys Ingersoll } 69347e946e7SWyllys Ingersoll 69447e946e7SWyllys Ingersoll /* create the TSS key object */ 69547e946e7SWyllys Ingersoll result = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, 69647e946e7SWyllys Ingersoll TSS_KEY_MIGRATABLE | initFlags | key_size, phKey); 69747e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 69847e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 69947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 70047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 70147e946e7SWyllys Ingersoll } 70247e946e7SWyllys Ingersoll 70347e946e7SWyllys Ingersoll result = set_public_modulus(hContext, *phKey, size_n, n); 70447e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 70547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 70647e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 70747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 70847e946e7SWyllys Ingersoll } 70947e946e7SWyllys Ingersoll 71047e946e7SWyllys Ingersoll /* set the private key data in the TSS object */ 71147e946e7SWyllys Ingersoll result = Tspi_SetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, 71247e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY, size_p, p); 71347e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 71447e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%x - %s", 71547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 71647e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 71747e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 71847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 71947e946e7SWyllys Ingersoll } 72047e946e7SWyllys Ingersoll 721*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_MIGRATION, 722*ab8176c2SWyllys Ingersoll *phKey, NULL); 72347e946e7SWyllys Ingersoll 72447e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { 72547e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(*phKey, 72647e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_ENCSCHEME, 72747e946e7SWyllys Ingersoll TSS_ES_RSAESPKCSV15))) { 72847e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", 72947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 73047e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 73147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 73247e946e7SWyllys Ingersoll } 73347e946e7SWyllys Ingersoll 73447e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(*phKey, 73547e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME, 73647e946e7SWyllys Ingersoll TSS_SS_RSASSAPKCS1V15_DER))) { 73747e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s\n", 73847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 73947e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 74047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 74147e946e7SWyllys Ingersoll } 74247e946e7SWyllys Ingersoll } 74347e946e7SWyllys Ingersoll 74447e946e7SWyllys Ingersoll result = Tspi_Key_WrapKey(*phKey, hParentKey, NULL_HPCRS); 74547e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 74647e946e7SWyllys Ingersoll stlogit("Tspi_Key_WrapKey: 0x%0x - %s", 74747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 74847e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 74947e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 75047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 75147e946e7SWyllys Ingersoll } 75247e946e7SWyllys Ingersoll 75347e946e7SWyllys Ingersoll return (CKR_OK); 75447e946e7SWyllys Ingersoll } 75547e946e7SWyllys Ingersoll 75647e946e7SWyllys Ingersoll /* 75747e946e7SWyllys Ingersoll * Create a TPM key blob for an imported key. This function is only called when 75847e946e7SWyllys Ingersoll * a key is in active use, so any failure should trickle through. 75947e946e7SWyllys Ingersoll */ 76047e946e7SWyllys Ingersoll static CK_RV 76147e946e7SWyllys Ingersoll token_wrap_key_object(TSS_HCONTEXT hContext, 76247e946e7SWyllys Ingersoll CK_OBJECT_HANDLE ckObject, 76347e946e7SWyllys Ingersoll TSS_HKEY hParentKey, TSS_HKEY *phKey) 76447e946e7SWyllys Ingersoll { 76547e946e7SWyllys Ingersoll CK_RV rc = CKR_OK; 76647e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr = NULL, *new_attr, *prime_attr; 76747e946e7SWyllys Ingersoll CK_ULONG class, key_type; 76847e946e7SWyllys Ingersoll OBJECT *obj; 76947e946e7SWyllys Ingersoll 77047e946e7SWyllys Ingersoll TSS_RESULT result; 77147e946e7SWyllys Ingersoll TSS_FLAG initFlags = 0; 77247e946e7SWyllys Ingersoll BYTE *rgbBlob; 77347e946e7SWyllys Ingersoll UINT32 ulBlobLen; 77447e946e7SWyllys Ingersoll 77547e946e7SWyllys Ingersoll if ((rc = object_mgr_find_in_map1(hContext, ckObject, &obj))) { 77647e946e7SWyllys Ingersoll return (rc); 77747e946e7SWyllys Ingersoll } 77847e946e7SWyllys Ingersoll 77947e946e7SWyllys Ingersoll /* if the object isn't a key, fail */ 78047e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_KEY_TYPE, 78147e946e7SWyllys Ingersoll &attr) == FALSE) { 78247e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 78347e946e7SWyllys Ingersoll } 78447e946e7SWyllys Ingersoll 78547e946e7SWyllys Ingersoll key_type = *((CK_ULONG *)attr->pValue); 78647e946e7SWyllys Ingersoll 78747e946e7SWyllys Ingersoll if (key_type != CKK_RSA) { 78847e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 78947e946e7SWyllys Ingersoll } 79047e946e7SWyllys Ingersoll 79147e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_CLASS, 79247e946e7SWyllys Ingersoll &attr) == FALSE) { 79347e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 79447e946e7SWyllys Ingersoll } 79547e946e7SWyllys Ingersoll 79647e946e7SWyllys Ingersoll class = *((CK_ULONG *)attr->pValue); 79747e946e7SWyllys Ingersoll 79847e946e7SWyllys Ingersoll if (class == CKO_PRIVATE_KEY) { 79947e946e7SWyllys Ingersoll /* 80047e946e7SWyllys Ingersoll * In order to create a full TSS key blob using a PKCS#11 80147e946e7SWyllys Ingersoll * private key object, we need one of the two primes, the 80247e946e7SWyllys Ingersoll * modulus and the private exponent and we need the public 80347e946e7SWyllys Ingersoll * exponent to be correct. 80447e946e7SWyllys Ingersoll */ 80547e946e7SWyllys Ingersoll 80647e946e7SWyllys Ingersoll /* 80747e946e7SWyllys Ingersoll * Check the least likely attribute to exist first, the 80847e946e7SWyllys Ingersoll * primes. 80947e946e7SWyllys Ingersoll */ 81047e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_PRIME_1, 81147e946e7SWyllys Ingersoll &prime_attr) == FALSE) { 81247e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, 81347e946e7SWyllys Ingersoll CKA_PRIME_2, &prime_attr) == FALSE) { 81447e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 81547e946e7SWyllys Ingersoll } 81647e946e7SWyllys Ingersoll } 81747e946e7SWyllys Ingersoll 81847e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 81947e946e7SWyllys Ingersoll if ((rc = util_check_public_exponent(obj->template))) { 82047e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 82147e946e7SWyllys Ingersoll } 82247e946e7SWyllys Ingersoll 82347e946e7SWyllys Ingersoll /* get the modulus */ 82447e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, CKA_MODULUS, 82547e946e7SWyllys Ingersoll &attr) == FALSE) { 82647e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 82747e946e7SWyllys Ingersoll } 82847e946e7SWyllys Ingersoll 82947e946e7SWyllys Ingersoll /* make sure the key size is usable */ 83047e946e7SWyllys Ingersoll initFlags = util_get_keysize_flag(attr->ulValueLen * 8); 83147e946e7SWyllys Ingersoll if (initFlags == 0) { 83247e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 83347e946e7SWyllys Ingersoll } 83447e946e7SWyllys Ingersoll 83547e946e7SWyllys Ingersoll /* generate the software based key */ 83647e946e7SWyllys Ingersoll if ((rc = token_wrap_sw_key(hContext, 83747e946e7SWyllys Ingersoll (int)attr->ulValueLen, attr->pValue, 83847e946e7SWyllys Ingersoll (int)prime_attr->ulValueLen, prime_attr->pValue, 83947e946e7SWyllys Ingersoll hParentKey, TSS_KEY_TYPE_LEGACY | TSS_KEY_NO_AUTHORIZATION, 84047e946e7SWyllys Ingersoll phKey))) { 84147e946e7SWyllys Ingersoll return (rc); 84247e946e7SWyllys Ingersoll } 84347e946e7SWyllys Ingersoll } else if (class == CKO_PUBLIC_KEY) { 84447e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 84547e946e7SWyllys Ingersoll if ((util_check_public_exponent(obj->template))) { 84647e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 84747e946e7SWyllys Ingersoll } 84847e946e7SWyllys Ingersoll 84947e946e7SWyllys Ingersoll /* grab the modulus to put into the TSS key object */ 85047e946e7SWyllys Ingersoll if (template_attribute_find(obj->template, 85147e946e7SWyllys Ingersoll CKA_MODULUS, &attr) == FALSE) { 85247e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 85347e946e7SWyllys Ingersoll } 85447e946e7SWyllys Ingersoll 85547e946e7SWyllys Ingersoll /* make sure the key size is usable */ 85647e946e7SWyllys Ingersoll initFlags = util_get_keysize_flag(attr->ulValueLen * 8); 85747e946e7SWyllys Ingersoll if (initFlags == 0) { 85847e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 85947e946e7SWyllys Ingersoll } 86047e946e7SWyllys Ingersoll 861*ab8176c2SWyllys Ingersoll initFlags |= TSS_KEY_MIGRATABLE | TSS_KEY_NO_AUTHORIZATION | 862*ab8176c2SWyllys Ingersoll TSS_KEY_TYPE_LEGACY; 86347e946e7SWyllys Ingersoll 86447e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 86547e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { 86647e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 86747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 86847e946e7SWyllys Ingersoll return (result); 86947e946e7SWyllys Ingersoll } 87047e946e7SWyllys Ingersoll 87147e946e7SWyllys Ingersoll if ((result = set_public_modulus(hContext, *phKey, 87247e946e7SWyllys Ingersoll attr->ulValueLen, attr->pValue))) { 87347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 87447e946e7SWyllys Ingersoll *phKey = NULL_HKEY; 87547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 87647e946e7SWyllys Ingersoll } 877*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, 878*ab8176c2SWyllys Ingersoll TSS_POLICY_MIGRATION, *phKey, NULL); 879*ab8176c2SWyllys Ingersoll if (result) { 880*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 881*ab8176c2SWyllys Ingersoll *phKey = NULL_HKEY; 882*ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 883*ab8176c2SWyllys Ingersoll } 884*ab8176c2SWyllys Ingersoll 885*ab8176c2SWyllys Ingersoll result = set_legacy_key_params(*phKey); 886*ab8176c2SWyllys Ingersoll if (result) { 887*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 888*ab8176c2SWyllys Ingersoll *phKey = NULL_HKEY; 889*ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 890*ab8176c2SWyllys Ingersoll } 89147e946e7SWyllys Ingersoll } else { 89247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 89347e946e7SWyllys Ingersoll } 89447e946e7SWyllys Ingersoll 89547e946e7SWyllys Ingersoll /* grab the entire key blob to put into the PKCS#11 object */ 89647e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(*phKey, TSS_TSPATTRIB_KEY_BLOB, 89747e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { 89847e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 89947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 90047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 90147e946e7SWyllys Ingersoll } 90247e946e7SWyllys Ingersoll 90347e946e7SWyllys Ingersoll /* insert the key blob into the object */ 90447e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, ulBlobLen, 90547e946e7SWyllys Ingersoll &new_attr))) { 90647e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 90747e946e7SWyllys Ingersoll return (rc); 90847e946e7SWyllys Ingersoll } 90947e946e7SWyllys Ingersoll (void) template_update_attribute(obj->template, new_attr); 91047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 91147e946e7SWyllys Ingersoll 91247e946e7SWyllys Ingersoll /* 91347e946e7SWyllys Ingersoll * If this is a token object, save it with the new attribute 91447e946e7SWyllys Ingersoll * so that we don't have to go down this path again. 91547e946e7SWyllys Ingersoll */ 91647e946e7SWyllys Ingersoll if (!object_is_session_object(obj)) { 91747e946e7SWyllys Ingersoll rc = save_token_object(hContext, obj); 91847e946e7SWyllys Ingersoll } 91947e946e7SWyllys Ingersoll 92047e946e7SWyllys Ingersoll return (rc); 92147e946e7SWyllys Ingersoll } 92247e946e7SWyllys Ingersoll 92347e946e7SWyllys Ingersoll static TSS_RESULT 924*ab8176c2SWyllys Ingersoll tss_assign_secret_key_policy(TSS_HCONTEXT hContext, TSS_FLAG policyType, 925*ab8176c2SWyllys Ingersoll TSS_HKEY hKey, CK_CHAR *passHash) 92647e946e7SWyllys Ingersoll { 92747e946e7SWyllys Ingersoll TSS_RESULT result; 92847e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 92947e946e7SWyllys Ingersoll 93047e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 931*ab8176c2SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, policyType, &hPolicy))) { 93247e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 93347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 93447e946e7SWyllys Ingersoll return (result); 93547e946e7SWyllys Ingersoll } 93647e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hPolicy, hKey))) { 93747e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", 93847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 93947e946e7SWyllys Ingersoll goto done; 94047e946e7SWyllys Ingersoll } 94147e946e7SWyllys Ingersoll if (passHash == NULL) { 94247e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_NONE, 94347e946e7SWyllys Ingersoll 0, NULL); 94447e946e7SWyllys Ingersoll } else { 94547e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 94647e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, passHash); 94747e946e7SWyllys Ingersoll } 94847e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 94947e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 95047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 95147e946e7SWyllys Ingersoll goto done; 95247e946e7SWyllys Ingersoll } 95347e946e7SWyllys Ingersoll done: 95447e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) 95547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPolicy); 95647e946e7SWyllys Ingersoll return (result); 95747e946e7SWyllys Ingersoll } 95847e946e7SWyllys Ingersoll 95947e946e7SWyllys Ingersoll /* 96047e946e7SWyllys Ingersoll * Take a key from the TSS store (on-disk) and load it into the TPM, wrapped 96147e946e7SWyllys Ingersoll * by an already TPM-resident key and protected with a PIN (optional). 96247e946e7SWyllys Ingersoll */ 96347e946e7SWyllys Ingersoll static CK_RV 96447e946e7SWyllys Ingersoll token_load_key( 96547e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 96647e946e7SWyllys Ingersoll CK_OBJECT_HANDLE ckKey, 96747e946e7SWyllys Ingersoll TSS_HKEY hParentKey, 96847e946e7SWyllys Ingersoll CK_CHAR_PTR passHash, 96947e946e7SWyllys Ingersoll TSS_HKEY *phKey) 97047e946e7SWyllys Ingersoll { 97147e946e7SWyllys Ingersoll TSS_RESULT result; 97247e946e7SWyllys Ingersoll CK_RV rc; 97347e946e7SWyllys Ingersoll 97447e946e7SWyllys Ingersoll /* 97547e946e7SWyllys Ingersoll * The key blob wasn't found, load the parts of the key 97647e946e7SWyllys Ingersoll * from the object DB and create a new key object that 97747e946e7SWyllys Ingersoll * gets loaded into the TPM, wrapped with the parent key. 97847e946e7SWyllys Ingersoll */ 97947e946e7SWyllys Ingersoll if ((rc = token_wrap_key_object(hContext, ckKey, 98047e946e7SWyllys Ingersoll hParentKey, phKey))) { 98147e946e7SWyllys Ingersoll return (rc); 98247e946e7SWyllys Ingersoll } 98347e946e7SWyllys Ingersoll 98447e946e7SWyllys Ingersoll /* 98547e946e7SWyllys Ingersoll * Assign the PIN hash (optional) to the newly loaded key object, 98647e946e7SWyllys Ingersoll * if this PIN is incorrect, the TPM will not be able to decrypt 98747e946e7SWyllys Ingersoll * the private key and use it. 98847e946e7SWyllys Ingersoll */ 989*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 990*ab8176c2SWyllys Ingersoll *phKey, passHash); 991*ab8176c2SWyllys Ingersoll 99247e946e7SWyllys Ingersoll return (result); 99347e946e7SWyllys Ingersoll } 99447e946e7SWyllys Ingersoll 99547e946e7SWyllys Ingersoll /* 99647e946e7SWyllys Ingersoll * Load the SRK into the TPM by referencing its well-known UUID and using the 99747e946e7SWyllys Ingersoll * default SRK PIN (20 bytes of 0x00). 99847e946e7SWyllys Ingersoll * 99947e946e7SWyllys Ingersoll * NOTE - if the SRK PIN is changed by an administrative tool, this code will 100047e946e7SWyllys Ingersoll * fail because it assumes that the well-known PIN is still being used. 100147e946e7SWyllys Ingersoll */ 100247e946e7SWyllys Ingersoll static TSS_RESULT 100347e946e7SWyllys Ingersoll token_load_srk(TSS_HCONTEXT hContext, TSS_HKEY *hSRK) 100447e946e7SWyllys Ingersoll { 100547e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 100647e946e7SWyllys Ingersoll TSS_RESULT result; 100747e946e7SWyllys Ingersoll TSS_UUID SRK_UUID = TSS_UUID_SRK; 100847e946e7SWyllys Ingersoll BYTE wellKnown[] = TSS_WELL_KNOWN_SECRET; 100947e946e7SWyllys Ingersoll TSS_HTPM hTPM; 101047e946e7SWyllys Ingersoll 101147e946e7SWyllys Ingersoll if ((result = Tspi_Context_GetTpmObject(hContext, &hTPM))) { 101247e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetTpmObject: 0x%0x - %s", 101347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 101447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 101547e946e7SWyllys Ingersoll } 101647e946e7SWyllys Ingersoll 101747e946e7SWyllys Ingersoll /* load the SRK */ 101847e946e7SWyllys Ingersoll if ((result = Tspi_Context_LoadKeyByUUID(hContext, 101947e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, SRK_UUID, hSRK))) { 102047e946e7SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByUUID: 0x%0x - %s", 102147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 102247e946e7SWyllys Ingersoll goto done; 102347e946e7SWyllys Ingersoll } 102447e946e7SWyllys Ingersoll if ((result = Tspi_GetPolicyObject(*hSRK, TSS_POLICY_USAGE, 102547e946e7SWyllys Ingersoll &hPolicy))) { 102647e946e7SWyllys Ingersoll stlogit("Tspi_GetPolicyObject: 0x%0x - %s", 102747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 102847e946e7SWyllys Ingersoll goto done; 102947e946e7SWyllys Ingersoll } 103047e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 103147e946e7SWyllys Ingersoll sizeof (wellKnown), wellKnown))) { 103247e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 103347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 103447e946e7SWyllys Ingersoll goto done; 103547e946e7SWyllys Ingersoll } 103647e946e7SWyllys Ingersoll 103747e946e7SWyllys Ingersoll done: 103847e946e7SWyllys Ingersoll return (result); 103947e946e7SWyllys Ingersoll } 104047e946e7SWyllys Ingersoll 104147e946e7SWyllys Ingersoll static TSS_RESULT 104247e946e7SWyllys Ingersoll tss_find_and_load_key(TSS_HCONTEXT hContext, 104347e946e7SWyllys Ingersoll char *keyid, TSS_UUID *uuid, TSS_HKEY hParent, 104447e946e7SWyllys Ingersoll BYTE *hash, TSS_HKEY *hKey) 104547e946e7SWyllys Ingersoll { 104647e946e7SWyllys Ingersoll TSS_RESULT result; 104747e946e7SWyllys Ingersoll 104847e946e7SWyllys Ingersoll if (local_uuid_is_null(uuid) && 104947e946e7SWyllys Ingersoll find_uuid(keyid, uuid)) { 105047e946e7SWyllys Ingersoll /* The UUID was not created or saved yet */ 105147e946e7SWyllys Ingersoll return (1); 105247e946e7SWyllys Ingersoll } 105347e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 105447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, *uuid, hKey); 105547e946e7SWyllys Ingersoll if (result) { 105647e946e7SWyllys Ingersoll stlogit("Tspi_Context_GetKeyByUUID: 0x%0x - %s", 105747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 105847e946e7SWyllys Ingersoll return (result); 105947e946e7SWyllys Ingersoll } 106047e946e7SWyllys Ingersoll 106147e946e7SWyllys Ingersoll if (hash != NULL) { 1062*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, 1063*ab8176c2SWyllys Ingersoll TSS_POLICY_USAGE, *hKey, (CK_BYTE *)hash); 106447e946e7SWyllys Ingersoll if (result) 106547e946e7SWyllys Ingersoll return (result); 106647e946e7SWyllys Ingersoll } 106747e946e7SWyllys Ingersoll 106847e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(*hKey, hParent); 106947e946e7SWyllys Ingersoll if (result) 107047e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 107147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 107247e946e7SWyllys Ingersoll 107347e946e7SWyllys Ingersoll return (result); 107447e946e7SWyllys Ingersoll } 107547e946e7SWyllys Ingersoll 107647e946e7SWyllys Ingersoll static TSS_RESULT 107747e946e7SWyllys Ingersoll token_load_public_root_key(TSS_HCONTEXT hContext) 107847e946e7SWyllys Ingersoll { 107947e946e7SWyllys Ingersoll TSS_RESULT result; 108047e946e7SWyllys Ingersoll TSS_HKEY hSRK; 108147e946e7SWyllys Ingersoll 108247e946e7SWyllys Ingersoll if (hPublicRootKey != NULL_HKEY) 108347e946e7SWyllys Ingersoll return (TSS_SUCCESS); 108447e946e7SWyllys Ingersoll 108547e946e7SWyllys Ingersoll if ((result = token_load_srk(hContext, &hSRK))) { 108647e946e7SWyllys Ingersoll return (result); 108747e946e7SWyllys Ingersoll } 108847e946e7SWyllys Ingersoll 108947e946e7SWyllys Ingersoll result = tss_find_and_load_key(hContext, 109047e946e7SWyllys Ingersoll TPMTOK_PUBLIC_ROOT_KEY_ID, 109147e946e7SWyllys Ingersoll &publicRootKeyUUID, hSRK, NULL, &hPublicRootKey); 109247e946e7SWyllys Ingersoll if (result) 109347e946e7SWyllys Ingersoll return (result); 109447e946e7SWyllys Ingersoll 109547e946e7SWyllys Ingersoll return (result); 109647e946e7SWyllys Ingersoll } 109747e946e7SWyllys Ingersoll 109847e946e7SWyllys Ingersoll static TSS_RESULT 1099*ab8176c2SWyllys Ingersoll set_legacy_key_params(TSS_HKEY hKey) 1100*ab8176c2SWyllys Ingersoll { 1101*ab8176c2SWyllys Ingersoll TSS_RESULT result; 1102*ab8176c2SWyllys Ingersoll 1103*ab8176c2SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(hKey, 1104*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, 1105*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_ENCSCHEME, 1106*ab8176c2SWyllys Ingersoll TSS_ES_RSAESPKCSV15))) { 1107*ab8176c2SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s", 1108*ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 1109*ab8176c2SWyllys Ingersoll return (result); 1110*ab8176c2SWyllys Ingersoll } 1111*ab8176c2SWyllys Ingersoll 1112*ab8176c2SWyllys Ingersoll if ((result = Tspi_SetAttribUint32(hKey, 1113*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEY_INFO, 1114*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_SIGSCHEME, 1115*ab8176c2SWyllys Ingersoll TSS_SS_RSASSAPKCS1V15_DER))) { 1116*ab8176c2SWyllys Ingersoll stlogit("Tspi_SetAttribUint32: 0x%0x - %s", 1117*ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 1118*ab8176c2SWyllys Ingersoll return (result); 1119*ab8176c2SWyllys Ingersoll } 1120*ab8176c2SWyllys Ingersoll 1121*ab8176c2SWyllys Ingersoll return (result); 1122*ab8176c2SWyllys Ingersoll } 1123*ab8176c2SWyllys Ingersoll 1124*ab8176c2SWyllys Ingersoll static TSS_RESULT 112547e946e7SWyllys Ingersoll tss_generate_key(TSS_HCONTEXT hContext, TSS_FLAG initFlags, BYTE *passHash, 112647e946e7SWyllys Ingersoll TSS_HKEY hParentKey, TSS_HKEY *phKey) 112747e946e7SWyllys Ingersoll { 112847e946e7SWyllys Ingersoll TSS_RESULT result; 112947e946e7SWyllys Ingersoll TSS_HPOLICY hMigPolicy; 113047e946e7SWyllys Ingersoll 113147e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 113247e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_RSAKEY, initFlags, phKey))) { 113347e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 113447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 113547e946e7SWyllys Ingersoll return (result); 113647e946e7SWyllys Ingersoll } 1137*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 1138*ab8176c2SWyllys Ingersoll *phKey, passHash); 113947e946e7SWyllys Ingersoll 114047e946e7SWyllys Ingersoll if (result) { 114147e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 114247e946e7SWyllys Ingersoll return (result); 114347e946e7SWyllys Ingersoll } 114447e946e7SWyllys Ingersoll 114547e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_MIG_TYPE(initFlags) == TSS_KEY_MIGRATABLE) { 114647e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 114747e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_MIGRATION, 114847e946e7SWyllys Ingersoll &hMigPolicy))) { 114947e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 115047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 115147e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 115247e946e7SWyllys Ingersoll return (result); 115347e946e7SWyllys Ingersoll } 115447e946e7SWyllys Ingersoll 115547e946e7SWyllys Ingersoll if (passHash == NULL) { 115647e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hMigPolicy, 115747e946e7SWyllys Ingersoll TSS_SECRET_MODE_NONE, 0, NULL); 115847e946e7SWyllys Ingersoll } else { 115947e946e7SWyllys Ingersoll result = Tspi_Policy_SetSecret(hMigPolicy, 116047e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, 20, passHash); 116147e946e7SWyllys Ingersoll } 116247e946e7SWyllys Ingersoll 116347e946e7SWyllys Ingersoll if (result != TSS_SUCCESS) { 116447e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 116547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 116647e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 116747e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 116847e946e7SWyllys Ingersoll return (result); 116947e946e7SWyllys Ingersoll } 117047e946e7SWyllys Ingersoll 117147e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hMigPolicy, *phKey))) { 117247e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: 0x%0x - %s", 117347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 117447e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 117547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 117647e946e7SWyllys Ingersoll return (result); 117747e946e7SWyllys Ingersoll } 117847e946e7SWyllys Ingersoll } 117947e946e7SWyllys Ingersoll 118047e946e7SWyllys Ingersoll if (TPMTOK_TSS_KEY_TYPE(initFlags) == TSS_KEY_TYPE_LEGACY) { 1181*ab8176c2SWyllys Ingersoll result = set_legacy_key_params(*phKey); 1182*ab8176c2SWyllys Ingersoll if (result) { 118347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 118447e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 118547e946e7SWyllys Ingersoll return (result); 118647e946e7SWyllys Ingersoll } 118747e946e7SWyllys Ingersoll } 118847e946e7SWyllys Ingersoll 118947e946e7SWyllys Ingersoll if ((result = Tspi_Key_CreateKey(*phKey, hParentKey, 0))) { 119047e946e7SWyllys Ingersoll stlogit("Tspi_Key_CreateKey: 0x%0x - %s", 119147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 119247e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, *phKey); 119347e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hMigPolicy); 119447e946e7SWyllys Ingersoll } 119547e946e7SWyllys Ingersoll 119647e946e7SWyllys Ingersoll return (result); 119747e946e7SWyllys Ingersoll } 119847e946e7SWyllys Ingersoll 119947e946e7SWyllys Ingersoll static TSS_RESULT 120047e946e7SWyllys Ingersoll tss_change_auth( 120147e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 120247e946e7SWyllys Ingersoll TSS_HKEY hObjectToChange, TSS_HKEY hParentObject, 120347e946e7SWyllys Ingersoll TSS_UUID objUUID, TSS_UUID parentUUID, 120447e946e7SWyllys Ingersoll CK_CHAR *passHash) 120547e946e7SWyllys Ingersoll { 120647e946e7SWyllys Ingersoll TSS_RESULT result; 120747e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy; 120847e946e7SWyllys Ingersoll TSS_HKEY oldkey; 120947e946e7SWyllys Ingersoll 121047e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 121147e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &hPolicy))) { 121247e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 121347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 121447e946e7SWyllys Ingersoll return (result); 121547e946e7SWyllys Ingersoll } 121647e946e7SWyllys Ingersoll 121747e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1, 121847e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, passHash))) { 121947e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 122047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 122147e946e7SWyllys Ingersoll return (result); 122247e946e7SWyllys Ingersoll } 122347e946e7SWyllys Ingersoll 122447e946e7SWyllys Ingersoll if ((result = Tspi_ChangeAuth(hObjectToChange, hParentObject, 122547e946e7SWyllys Ingersoll hPolicy))) { 122647e946e7SWyllys Ingersoll stlogit("Tspi_ChangeAuth: 0x%0x - %s", 122747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 122847e946e7SWyllys Ingersoll } 122947e946e7SWyllys Ingersoll /* 123047e946e7SWyllys Ingersoll * Update the PS key by unregistering the key UUID and then 123147e946e7SWyllys Ingersoll * re-registering with the same UUID. This forces the updated 123247e946e7SWyllys Ingersoll * auth data associated with the key to be stored in PS so 123347e946e7SWyllys Ingersoll * the new PIN can be used next time. 123447e946e7SWyllys Ingersoll */ 123547e946e7SWyllys Ingersoll if ((result = Tspi_Context_UnregisterKey(hContext, 123647e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, objUUID, &oldkey))) 123747e946e7SWyllys Ingersoll stlogit("Tspi_Context_UnregisterKey: 0x%0x - %s", 123847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 123947e946e7SWyllys Ingersoll 124047e946e7SWyllys Ingersoll if ((result = Tspi_Context_RegisterKey(hContext, hObjectToChange, 124147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, objUUID, TSS_PS_TYPE_USER, parentUUID))) 124247e946e7SWyllys Ingersoll stlogit("Tspi_Context_RegisterKey: 0x%0x - %s", 124347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 124447e946e7SWyllys Ingersoll 124547e946e7SWyllys Ingersoll return (result); 124647e946e7SWyllys Ingersoll } 124747e946e7SWyllys Ingersoll 124847e946e7SWyllys Ingersoll static CK_RV 124947e946e7SWyllys Ingersoll token_generate_leaf_key(TSS_HCONTEXT hContext, 125047e946e7SWyllys Ingersoll int key_type, CK_CHAR_PTR passHash, TSS_HKEY *phKey) 125147e946e7SWyllys Ingersoll { 125247e946e7SWyllys Ingersoll CK_RV rc = CKR_FUNCTION_FAILED; 125347e946e7SWyllys Ingersoll TSS_RESULT result; 125447e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 125547e946e7SWyllys Ingersoll TSS_UUID newuuid, parentUUID; 125647e946e7SWyllys Ingersoll char *keyid; 125747e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_MIGRATABLE | 125847e946e7SWyllys Ingersoll TSS_KEY_TYPE_BIND | TSS_KEY_SIZE_2048 | TSS_KEY_AUTHORIZATION; 125947e946e7SWyllys Ingersoll 126047e946e7SWyllys Ingersoll switch (key_type) { 126147e946e7SWyllys Ingersoll case TPMTOK_PUBLIC_LEAF_KEY: 126247e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 126347e946e7SWyllys Ingersoll keyid = TPMTOK_PUBLIC_LEAF_KEY_ID; 126447e946e7SWyllys Ingersoll local_uuid_copy(&parentUUID, &publicRootKeyUUID); 126547e946e7SWyllys Ingersoll break; 126647e946e7SWyllys Ingersoll case TPMTOK_PRIVATE_LEAF_KEY: 126747e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 126847e946e7SWyllys Ingersoll keyid = TPMTOK_PRIVATE_LEAF_KEY_ID; 126947e946e7SWyllys Ingersoll local_uuid_copy(&parentUUID, &privateRootKeyUUID); 127047e946e7SWyllys Ingersoll break; 127147e946e7SWyllys Ingersoll default: 127247e946e7SWyllys Ingersoll stlogit("Unknown key type 0x%0x", key_type); 127347e946e7SWyllys Ingersoll goto done; 127447e946e7SWyllys Ingersoll break; 127547e946e7SWyllys Ingersoll } 127647e946e7SWyllys Ingersoll 127747e946e7SWyllys Ingersoll if (result = tss_generate_key(hContext, initFlags, passHash, 127847e946e7SWyllys Ingersoll hParentKey, phKey)) { 127947e946e7SWyllys Ingersoll return (rc); 128047e946e7SWyllys Ingersoll } 128147e946e7SWyllys Ingersoll 128247e946e7SWyllys Ingersoll /* 128347e946e7SWyllys Ingersoll * - generate newUUID 128447e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 128547e946e7SWyllys Ingersoll * USER, newUUID, USER, parentUUID); 128647e946e7SWyllys Ingersoll * - store newUUID 128747e946e7SWyllys Ingersoll */ 128847e946e7SWyllys Ingersoll (void) local_uuid_generate(&newuuid); 128947e946e7SWyllys Ingersoll 129047e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, *phKey, 129147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, newuuid, 129247e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, parentUUID); 129347e946e7SWyllys Ingersoll if (result == TSS_SUCCESS) { 129447e946e7SWyllys Ingersoll int ret; 129547e946e7SWyllys Ingersoll /* 129647e946e7SWyllys Ingersoll * Add the UUID to the token UUID index. 129747e946e7SWyllys Ingersoll */ 129847e946e7SWyllys Ingersoll ret = add_uuid(keyid, &newuuid); 129947e946e7SWyllys Ingersoll 130047e946e7SWyllys Ingersoll if (ret) 130147e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 130247e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, newuuid, phKey); 130347e946e7SWyllys Ingersoll else 130447e946e7SWyllys Ingersoll rc = CKR_OK; 130547e946e7SWyllys Ingersoll } 130647e946e7SWyllys Ingersoll 130747e946e7SWyllys Ingersoll done: 130847e946e7SWyllys Ingersoll return (rc); 130947e946e7SWyllys Ingersoll } 131047e946e7SWyllys Ingersoll 131147e946e7SWyllys Ingersoll /* 131247e946e7SWyllys Ingersoll * PINs are verified by attempting to bind/unbind random data using a 131347e946e7SWyllys Ingersoll * TPM resident key that has the PIN being tested assigned as its "secret". 131447e946e7SWyllys Ingersoll * If the PIN is incorrect, the unbind operation will fail. 131547e946e7SWyllys Ingersoll */ 131647e946e7SWyllys Ingersoll static CK_RV 131747e946e7SWyllys Ingersoll token_verify_pin(TSS_HCONTEXT hContext, TSS_HKEY hKey) 131847e946e7SWyllys Ingersoll { 131947e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 132047e946e7SWyllys Ingersoll UINT32 ulUnboundDataLen; 132147e946e7SWyllys Ingersoll BYTE *rgbUnboundData = NULL; 132247e946e7SWyllys Ingersoll BYTE rgbData[16]; 132347e946e7SWyllys Ingersoll TSS_RESULT result; 132447e946e7SWyllys Ingersoll CK_RV rc = CKR_FUNCTION_FAILED; 132547e946e7SWyllys Ingersoll 132647e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 132747e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 132847e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 132947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 133047e946e7SWyllys Ingersoll goto done; 133147e946e7SWyllys Ingersoll } 133247e946e7SWyllys Ingersoll 133347e946e7SWyllys Ingersoll /* Use some random data */ 133447e946e7SWyllys Ingersoll rc = token_rng(hContext, rgbData, sizeof (rgbData)); 133547e946e7SWyllys Ingersoll if (rc) 133647e946e7SWyllys Ingersoll goto done; 133747e946e7SWyllys Ingersoll 133847e946e7SWyllys Ingersoll if ((result = Tspi_Data_Bind(hEncData, hKey, 133947e946e7SWyllys Ingersoll sizeof (rgbData), rgbData))) { 134047e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 134147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 134247e946e7SWyllys Ingersoll goto done; 134347e946e7SWyllys Ingersoll } 134447e946e7SWyllys Ingersoll 134547e946e7SWyllys Ingersoll /* unbind the junk data to test the key's auth data */ 134647e946e7SWyllys Ingersoll result = Tspi_Data_Unbind(hEncData, hKey, &ulUnboundDataLen, 134747e946e7SWyllys Ingersoll &rgbUnboundData); 1348*ab8176c2SWyllys Ingersoll if (result == TPM_E_AUTHFAIL) { 134947e946e7SWyllys Ingersoll rc = CKR_PIN_INCORRECT; 135047e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 135147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 135247e946e7SWyllys Ingersoll goto done; 135347e946e7SWyllys Ingersoll } else if (result != TSS_SUCCESS) { 135447e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 135547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 135647e946e7SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 135747e946e7SWyllys Ingersoll goto done; 135847e946e7SWyllys Ingersoll } 135947e946e7SWyllys Ingersoll 136047e946e7SWyllys Ingersoll if (memcmp(rgbUnboundData, rgbData, ulUnboundDataLen)) 136147e946e7SWyllys Ingersoll rc = CKR_PIN_INCORRECT; 136247e946e7SWyllys Ingersoll else 136347e946e7SWyllys Ingersoll rc = CKR_OK; 136447e946e7SWyllys Ingersoll 136547e946e7SWyllys Ingersoll done: 136647e946e7SWyllys Ingersoll if (rgbUnboundData != NULL) 136747e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbUnboundData); 136847e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hEncData); 136947e946e7SWyllys Ingersoll return (rc); 137047e946e7SWyllys Ingersoll } 137147e946e7SWyllys Ingersoll 137247e946e7SWyllys Ingersoll static CK_RV 137347e946e7SWyllys Ingersoll token_create_private_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) 137447e946e7SWyllys Ingersoll { 137547e946e7SWyllys Ingersoll CK_RV rc; 137647e946e7SWyllys Ingersoll TSS_RESULT result; 137747e946e7SWyllys Ingersoll int ret; 137847e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | 137947e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; 138047e946e7SWyllys Ingersoll TSS_UUID SRK_UUID = TSS_UUID_SRK; 138147e946e7SWyllys Ingersoll TSS_HKEY hSRK; 138247e946e7SWyllys Ingersoll 138347e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 138447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 138547e946e7SWyllys Ingersoll 138647e946e7SWyllys Ingersoll /* 138747e946e7SWyllys Ingersoll * - create UUID privateRootKeyUUID 138847e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 138947e946e7SWyllys Ingersoll * USER, privateRootKeyUUID, system, UUID_SRK); 139047e946e7SWyllys Ingersoll * - store privateRootKeyUUID in users private token space. 139147e946e7SWyllys Ingersoll */ 139247e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, 139347e946e7SWyllys Ingersoll &hPrivateRootKey))) { 139447e946e7SWyllys Ingersoll return (result); 139547e946e7SWyllys Ingersoll } 139647e946e7SWyllys Ingersoll if (local_uuid_is_null(&privateRootKeyUUID)) 139747e946e7SWyllys Ingersoll local_uuid_generate(&privateRootKeyUUID); 139847e946e7SWyllys Ingersoll 139947e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, hPrivateRootKey, 140047e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 140147e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, SRK_UUID); 140247e946e7SWyllys Ingersoll 140347e946e7SWyllys Ingersoll if (result) { 140447e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 140547e946e7SWyllys Ingersoll return (result); 140647e946e7SWyllys Ingersoll } 140747e946e7SWyllys Ingersoll 140847e946e7SWyllys Ingersoll ret = add_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, &privateRootKeyUUID); 140947e946e7SWyllys Ingersoll if (ret) { 141047e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 141147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 141247e946e7SWyllys Ingersoll &hPrivateRootKey); 141347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 141447e946e7SWyllys Ingersoll } 141547e946e7SWyllys Ingersoll 141647e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPrivateRootKey, hSRK))) { 141747e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 141847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 141947e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 142047e946e7SWyllys Ingersoll 142147e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); 142247e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 142347e946e7SWyllys Ingersoll 142447e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 142547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 142647e946e7SWyllys Ingersoll } 142747e946e7SWyllys Ingersoll 142847e946e7SWyllys Ingersoll 142947e946e7SWyllys Ingersoll /* generate the private leaf key */ 143047e946e7SWyllys Ingersoll if ((rc = token_generate_leaf_key(hContext, 143147e946e7SWyllys Ingersoll TPMTOK_PRIVATE_LEAF_KEY, 143247e946e7SWyllys Ingersoll pinHash, &hPrivateLeafKey))) { 143347e946e7SWyllys Ingersoll return (rc); 143447e946e7SWyllys Ingersoll } 143547e946e7SWyllys Ingersoll 143647e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPrivateLeafKey, hPrivateRootKey))) { 143747e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 143847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 143947e946e7SWyllys Ingersoll 144047e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 144147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateLeafKeyUUID, 144247e946e7SWyllys Ingersoll &hPrivateLeafKey); 144347e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_LEAF_KEY_ID); 144447e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 144547e946e7SWyllys Ingersoll 144647e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 144747e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, privateRootKeyUUID, 144847e946e7SWyllys Ingersoll &hPrivateRootKey); 144947e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID); 145047e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 145147e946e7SWyllys Ingersoll 145247e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 145347e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 145447e946e7SWyllys Ingersoll 145547e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateLeafKey); 145647e946e7SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 145747e946e7SWyllys Ingersoll 145847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 145947e946e7SWyllys Ingersoll } 146047e946e7SWyllys Ingersoll return (rc); 146147e946e7SWyllys Ingersoll } 146247e946e7SWyllys Ingersoll 146347e946e7SWyllys Ingersoll static CK_RV 146447e946e7SWyllys Ingersoll token_create_public_tree(TSS_HCONTEXT hContext, CK_BYTE *pinHash) 146547e946e7SWyllys Ingersoll { 146647e946e7SWyllys Ingersoll CK_RV rc; 146747e946e7SWyllys Ingersoll TSS_RESULT result; 146847e946e7SWyllys Ingersoll int ret; 146947e946e7SWyllys Ingersoll TSS_FLAG initFlags = TSS_KEY_SIZE_2048 | 147047e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_TYPE_STORAGE; 147147e946e7SWyllys Ingersoll TSS_UUID srk_uuid = TSS_UUID_SRK; 147247e946e7SWyllys Ingersoll TSS_HKEY hSRK; 147347e946e7SWyllys Ingersoll 147447e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 147547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 147647e946e7SWyllys Ingersoll 147747e946e7SWyllys Ingersoll /* 147847e946e7SWyllys Ingersoll * - create publicRootKeyUUID 147947e946e7SWyllys Ingersoll * - Tspi_Context_RegisterKey(hContext, hPublicRootKey, 148047e946e7SWyllys Ingersoll * USER, publicRootKeyUUID, system, UUID_SRK); 148147e946e7SWyllys Ingersoll * - store publicRootKeyUUID in users private token space. 148247e946e7SWyllys Ingersoll */ 148347e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, NULL, hSRK, 148447e946e7SWyllys Ingersoll &hPublicRootKey))) { 148547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 148647e946e7SWyllys Ingersoll } 148747e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID)) 148847e946e7SWyllys Ingersoll local_uuid_generate(&publicRootKeyUUID); 148947e946e7SWyllys Ingersoll 149047e946e7SWyllys Ingersoll result = Tspi_Context_RegisterKey(hContext, hPublicRootKey, 149147e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 149247e946e7SWyllys Ingersoll TSS_PS_TYPE_SYSTEM, srk_uuid); 149347e946e7SWyllys Ingersoll 149447e946e7SWyllys Ingersoll if (result) { 149547e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 149647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 149747e946e7SWyllys Ingersoll } 149847e946e7SWyllys Ingersoll 149947e946e7SWyllys Ingersoll ret = add_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID); 150047e946e7SWyllys Ingersoll if (ret) { 150147e946e7SWyllys Ingersoll result = Tspi_Context_UnregisterKey(hContext, 150247e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 150347e946e7SWyllys Ingersoll &hPublicRootKey); 150447e946e7SWyllys Ingersoll /* does result matter here? */ 150547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 150647e946e7SWyllys Ingersoll } 150747e946e7SWyllys Ingersoll 150847e946e7SWyllys Ingersoll /* Load the newly created publicRootKey into the TPM using the SRK */ 150947e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPublicRootKey, hSRK))) { 151047e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%x - %s", result, 151147e946e7SWyllys Ingersoll Trspi_Error_String(result)); 151247e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 151347e946e7SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 151447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 151547e946e7SWyllys Ingersoll } 151647e946e7SWyllys Ingersoll 151747e946e7SWyllys Ingersoll /* create the SO's leaf key */ 151847e946e7SWyllys Ingersoll if ((rc = token_generate_leaf_key(hContext, TPMTOK_PUBLIC_LEAF_KEY, 151947e946e7SWyllys Ingersoll pinHash, &hPublicLeafKey))) { 152047e946e7SWyllys Ingersoll return (rc); 152147e946e7SWyllys Ingersoll } 152247e946e7SWyllys Ingersoll 152347e946e7SWyllys Ingersoll if ((result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey))) { 152447e946e7SWyllys Ingersoll stlogit("Tspi_Key_LoadKey: 0x%0x - %s", 152547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 152647e946e7SWyllys Ingersoll 152747e946e7SWyllys Ingersoll /* Unregister keys and clear UUIDs */ 152847e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 152947e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicLeafKeyUUID, 153047e946e7SWyllys Ingersoll &hPublicLeafKey); 153147e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID); 153247e946e7SWyllys Ingersoll 153347e946e7SWyllys Ingersoll (void) Tspi_Context_UnregisterKey(hContext, 153447e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, 153547e946e7SWyllys Ingersoll &hPublicRootKey); 153647e946e7SWyllys Ingersoll (void) remove_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID); 153747e946e7SWyllys Ingersoll 153847e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 153947e946e7SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 154047e946e7SWyllys Ingersoll 154147e946e7SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicLeafKey); 154247e946e7SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 154347e946e7SWyllys Ingersoll 154447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 154547e946e7SWyllys Ingersoll } 154647e946e7SWyllys Ingersoll 154747e946e7SWyllys Ingersoll return (rc); 154847e946e7SWyllys Ingersoll } 154947e946e7SWyllys Ingersoll 155047e946e7SWyllys Ingersoll CK_RV 155147e946e7SWyllys Ingersoll token_specific_login( 155247e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 155347e946e7SWyllys Ingersoll CK_USER_TYPE userType, 155447e946e7SWyllys Ingersoll CK_CHAR_PTR pPin, 155547e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 155647e946e7SWyllys Ingersoll { 155747e946e7SWyllys Ingersoll CK_RV rc; 155847e946e7SWyllys Ingersoll CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; 155947e946e7SWyllys Ingersoll TSS_RESULT result; 156047e946e7SWyllys Ingersoll TSS_HKEY hSRK; 156147e946e7SWyllys Ingersoll 156247e946e7SWyllys Ingersoll /* Make sure the SRK is loaded into the TPM */ 156347e946e7SWyllys Ingersoll if ((result = token_load_srk(hContext, &hSRK))) { 156447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 156547e946e7SWyllys Ingersoll } 156647e946e7SWyllys Ingersoll 156747e946e7SWyllys Ingersoll if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { 156847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 156947e946e7SWyllys Ingersoll } 157047e946e7SWyllys Ingersoll 157147e946e7SWyllys Ingersoll if (userType == CKU_USER) { 157247e946e7SWyllys Ingersoll /* 157347e946e7SWyllys Ingersoll * If the public root key doesn't exist yet, 157447e946e7SWyllys Ingersoll * the SO hasn't init'd the token. 157547e946e7SWyllys Ingersoll */ 157647e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) { 157747e946e7SWyllys Ingersoll if (result == TPM_E_DECRYPT_ERROR) { 157847e946e7SWyllys Ingersoll return (CKR_USER_PIN_NOT_INITIALIZED); 157947e946e7SWyllys Ingersoll } 158047e946e7SWyllys Ingersoll } 158147e946e7SWyllys Ingersoll 158247e946e7SWyllys Ingersoll /* 158347e946e7SWyllys Ingersoll * - find privateRootKeyUUID 158447e946e7SWyllys Ingersoll * - load by UUID (SRK parent) 158547e946e7SWyllys Ingersoll */ 158647e946e7SWyllys Ingersoll if (local_uuid_is_null(&privateRootKeyUUID) && 158747e946e7SWyllys Ingersoll find_uuid(TPMTOK_PRIVATE_ROOT_KEY_ID, 158847e946e7SWyllys Ingersoll &privateRootKeyUUID)) { 158947e946e7SWyllys Ingersoll if (memcmp(hash_sha, 159047e946e7SWyllys Ingersoll default_user_pin_sha, 159147e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 159247e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 159347e946e7SWyllys Ingersoll 159447e946e7SWyllys Ingersoll not_initialized = 1; 159547e946e7SWyllys Ingersoll return (CKR_OK); 159647e946e7SWyllys Ingersoll } 159747e946e7SWyllys Ingersoll 159847e946e7SWyllys Ingersoll if ((rc = verify_user_pin(hContext, hash_sha))) { 159947e946e7SWyllys Ingersoll return (rc); 160047e946e7SWyllys Ingersoll } 160147e946e7SWyllys Ingersoll 160247e946e7SWyllys Ingersoll (void) memcpy(current_user_pin_sha, hash_sha, 160347e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH); 160447e946e7SWyllys Ingersoll 160547e946e7SWyllys Ingersoll rc = load_private_token_objects(hContext); 160647e946e7SWyllys Ingersoll if (rc == CKR_OK) { 160747e946e7SWyllys Ingersoll (void) XProcLock(xproclock); 160847e946e7SWyllys Ingersoll global_shm->priv_loaded = TRUE; 160947e946e7SWyllys Ingersoll (void) XProcUnLock(xproclock); 161047e946e7SWyllys Ingersoll } 161147e946e7SWyllys Ingersoll } else { 161247e946e7SWyllys Ingersoll /* 161347e946e7SWyllys Ingersoll * SO login logic: 161447e946e7SWyllys Ingersoll * 161547e946e7SWyllys Ingersoll * - find publicRootKey UUID 161647e946e7SWyllys Ingersoll * - load by UUID wrap with hSRK from above 161747e946e7SWyllys Ingersoll */ 161847e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID) && 161947e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, 162047e946e7SWyllys Ingersoll &publicRootKeyUUID)) { 162147e946e7SWyllys Ingersoll if (memcmp(hash_sha, 162247e946e7SWyllys Ingersoll default_so_pin_sha, 162347e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 162447e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 162547e946e7SWyllys Ingersoll 162647e946e7SWyllys Ingersoll not_initialized = 1; 162747e946e7SWyllys Ingersoll return (CKR_OK); 162847e946e7SWyllys Ingersoll 162947e946e7SWyllys Ingersoll } 163047e946e7SWyllys Ingersoll if (hPublicRootKey == NULL_HKEY) { 163147e946e7SWyllys Ingersoll result = tss_find_and_load_key( 163247e946e7SWyllys Ingersoll hContext, 163347e946e7SWyllys Ingersoll TPMTOK_PUBLIC_ROOT_KEY_ID, 163447e946e7SWyllys Ingersoll &publicRootKeyUUID, hSRK, NULL, 163547e946e7SWyllys Ingersoll &hPublicRootKey); 163647e946e7SWyllys Ingersoll 163747e946e7SWyllys Ingersoll if (result) 163847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 163947e946e7SWyllys Ingersoll } 164047e946e7SWyllys Ingersoll 164147e946e7SWyllys Ingersoll /* find, load the public leaf key */ 164247e946e7SWyllys Ingersoll if (hPublicLeafKey == NULL_HKEY) { 164347e946e7SWyllys Ingersoll result = tss_find_and_load_key( 164447e946e7SWyllys Ingersoll hContext, 164547e946e7SWyllys Ingersoll TPMTOK_PUBLIC_LEAF_KEY_ID, 164647e946e7SWyllys Ingersoll &publicLeafKeyUUID, hPublicRootKey, hash_sha, 164747e946e7SWyllys Ingersoll &hPublicLeafKey); 164847e946e7SWyllys Ingersoll if (result) 164947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 165047e946e7SWyllys Ingersoll } 165147e946e7SWyllys Ingersoll 165247e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { 165347e946e7SWyllys Ingersoll return (rc); 165447e946e7SWyllys Ingersoll } 165547e946e7SWyllys Ingersoll 165647e946e7SWyllys Ingersoll (void) memcpy(current_so_pin_sha, hash_sha, SHA1_DIGEST_LENGTH); 165747e946e7SWyllys Ingersoll } 165847e946e7SWyllys Ingersoll 165947e946e7SWyllys Ingersoll return (rc); 166047e946e7SWyllys Ingersoll } 166147e946e7SWyllys Ingersoll 166247e946e7SWyllys Ingersoll CK_RV 166347e946e7SWyllys Ingersoll token_specific_logout(TSS_HCONTEXT hContext) 166447e946e7SWyllys Ingersoll { 166547e946e7SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 166647e946e7SWyllys Ingersoll Tspi_Key_UnloadKey(hPrivateLeafKey); 166747e946e7SWyllys Ingersoll hPrivateLeafKey = NULL_HKEY; 166847e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 166947e946e7SWyllys Ingersoll Tspi_Key_UnloadKey(hPublicLeafKey); 167047e946e7SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 167147e946e7SWyllys Ingersoll } 167247e946e7SWyllys Ingersoll 167347e946e7SWyllys Ingersoll local_uuid_clear(&publicRootKeyUUID); 167447e946e7SWyllys Ingersoll local_uuid_clear(&publicLeafKeyUUID); 167547e946e7SWyllys Ingersoll local_uuid_clear(&privateRootKeyUUID); 167647e946e7SWyllys Ingersoll local_uuid_clear(&privateLeafKeyUUID); 167747e946e7SWyllys Ingersoll 167847e946e7SWyllys Ingersoll (void) memset(current_so_pin_sha, 0, SHA1_DIGEST_LENGTH); 167947e946e7SWyllys Ingersoll (void) memset(current_user_pin_sha, 0, SHA1_DIGEST_LENGTH); 168047e946e7SWyllys Ingersoll 168147e946e7SWyllys Ingersoll (void) object_mgr_purge_private_token_objects(hContext); 168247e946e7SWyllys Ingersoll 168347e946e7SWyllys Ingersoll return (CKR_OK); 168447e946e7SWyllys Ingersoll } 168547e946e7SWyllys Ingersoll 168647e946e7SWyllys Ingersoll /*ARGSUSED*/ 168747e946e7SWyllys Ingersoll CK_RV 168847e946e7SWyllys Ingersoll token_specific_init_pin(TSS_HCONTEXT hContext, 168947e946e7SWyllys Ingersoll CK_CHAR_PTR pPin, CK_ULONG ulPinLen) 169047e946e7SWyllys Ingersoll { 169147e946e7SWyllys Ingersoll /* 169247e946e7SWyllys Ingersoll * Since the SO must log in before calling C_InitPIN, we will 169347e946e7SWyllys Ingersoll * be able to return (CKR_OK) automatically here. 169447e946e7SWyllys Ingersoll * This is because the USER key structure is created at the 169547e946e7SWyllys Ingersoll * time of her first login, not at C_InitPIN time. 169647e946e7SWyllys Ingersoll */ 169747e946e7SWyllys Ingersoll return (CKR_OK); 169847e946e7SWyllys Ingersoll } 169947e946e7SWyllys Ingersoll 170047e946e7SWyllys Ingersoll static CK_RV 170147e946e7SWyllys Ingersoll check_pin_properties(CK_USER_TYPE userType, CK_BYTE *pinHash, 170247e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 170347e946e7SWyllys Ingersoll { 170447e946e7SWyllys Ingersoll /* make sure the new PIN is different */ 170547e946e7SWyllys Ingersoll if (userType == CKU_USER) { 170647e946e7SWyllys Ingersoll if (!memcmp(pinHash, default_user_pin_sha, 170747e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 170847e946e7SWyllys Ingersoll LogError1("new PIN must not be the default"); 170947e946e7SWyllys Ingersoll return (CKR_PIN_INVALID); 171047e946e7SWyllys Ingersoll } 171147e946e7SWyllys Ingersoll } else { 171247e946e7SWyllys Ingersoll if (!memcmp(pinHash, default_so_pin_sha, 171347e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 171447e946e7SWyllys Ingersoll LogError1("new PIN must not be the default"); 171547e946e7SWyllys Ingersoll return (CKR_PIN_INVALID); 171647e946e7SWyllys Ingersoll } 171747e946e7SWyllys Ingersoll } 171847e946e7SWyllys Ingersoll 171947e946e7SWyllys Ingersoll if (ulPinLen > MAX_PIN_LEN || ulPinLen < MIN_PIN_LEN) { 172047e946e7SWyllys Ingersoll LogError1("New PIN is out of size range"); 172147e946e7SWyllys Ingersoll return (CKR_PIN_LEN_RANGE); 172247e946e7SWyllys Ingersoll } 172347e946e7SWyllys Ingersoll 172447e946e7SWyllys Ingersoll return (CKR_OK); 172547e946e7SWyllys Ingersoll } 172647e946e7SWyllys Ingersoll 172747e946e7SWyllys Ingersoll /* 172847e946e7SWyllys Ingersoll * This function is called from set_pin only, where a non-logged-in public 172947e946e7SWyllys Ingersoll * session can provide the user pin which must be verified. This function 173047e946e7SWyllys Ingersoll * assumes that the pin has already been set once, so there's no migration 173147e946e7SWyllys Ingersoll * path option or checking of the default user pin. 173247e946e7SWyllys Ingersoll */ 173347e946e7SWyllys Ingersoll static CK_RV 173447e946e7SWyllys Ingersoll verify_user_pin(TSS_HCONTEXT hContext, CK_BYTE *hash_sha) 173547e946e7SWyllys Ingersoll { 173647e946e7SWyllys Ingersoll CK_RV rc; 173747e946e7SWyllys Ingersoll TSS_RESULT result; 173847e946e7SWyllys Ingersoll TSS_HKEY hSRK; 173947e946e7SWyllys Ingersoll 174047e946e7SWyllys Ingersoll if (token_load_srk(hContext, &hSRK)) 174147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 174247e946e7SWyllys Ingersoll 174347e946e7SWyllys Ingersoll /* 174447e946e7SWyllys Ingersoll * Verify the user by loading the privateLeafKey 174547e946e7SWyllys Ingersoll * into the TPM (if it's not already) and then 174647e946e7SWyllys Ingersoll * call the verify_pin operation. 174747e946e7SWyllys Ingersoll * 174847e946e7SWyllys Ingersoll * The hashed PIN is assigned to the private leaf key. 174947e946e7SWyllys Ingersoll * If it is incorrect (not the same as the one originally 175047e946e7SWyllys Ingersoll * used when the key was created), the verify operation 175147e946e7SWyllys Ingersoll * will fail. 175247e946e7SWyllys Ingersoll */ 175347e946e7SWyllys Ingersoll if (hPrivateRootKey == NULL_HKEY) { 175447e946e7SWyllys Ingersoll result = tss_find_and_load_key( 175547e946e7SWyllys Ingersoll hContext, 175647e946e7SWyllys Ingersoll TPMTOK_PRIVATE_ROOT_KEY_ID, 175747e946e7SWyllys Ingersoll &privateRootKeyUUID, hSRK, NULL, &hPrivateRootKey); 175847e946e7SWyllys Ingersoll if (result) 175947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 176047e946e7SWyllys Ingersoll } 176147e946e7SWyllys Ingersoll 176247e946e7SWyllys Ingersoll if (hPrivateLeafKey == NULL_HKEY) { 176347e946e7SWyllys Ingersoll result = tss_find_and_load_key( 176447e946e7SWyllys Ingersoll hContext, 176547e946e7SWyllys Ingersoll TPMTOK_PRIVATE_LEAF_KEY_ID, 176647e946e7SWyllys Ingersoll &privateLeafKeyUUID, hPrivateRootKey, hash_sha, 176747e946e7SWyllys Ingersoll &hPrivateLeafKey); 176847e946e7SWyllys Ingersoll 176947e946e7SWyllys Ingersoll if (result) 177047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 177147e946e7SWyllys Ingersoll } 177247e946e7SWyllys Ingersoll 177347e946e7SWyllys Ingersoll /* 177447e946e7SWyllys Ingersoll * Verify that the PIN is correct by attempting to wrap/unwrap some 177547e946e7SWyllys Ingersoll * random data. 177647e946e7SWyllys Ingersoll */ 177747e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPrivateLeafKey))) { 177847e946e7SWyllys Ingersoll return (rc); 177947e946e7SWyllys Ingersoll } 178047e946e7SWyllys Ingersoll 178147e946e7SWyllys Ingersoll return (CKR_OK); 178247e946e7SWyllys Ingersoll } 178347e946e7SWyllys Ingersoll 178447e946e7SWyllys Ingersoll CK_RV 178547e946e7SWyllys Ingersoll token_specific_set_pin(ST_SESSION_HANDLE session, 178647e946e7SWyllys Ingersoll CK_CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, 178747e946e7SWyllys Ingersoll CK_CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) 178847e946e7SWyllys Ingersoll { 178947e946e7SWyllys Ingersoll SESSION *sess = session_mgr_find(session.sessionh); 179047e946e7SWyllys Ingersoll CK_BYTE oldpin_hash[SHA1_DIGEST_LENGTH]; 179147e946e7SWyllys Ingersoll CK_BYTE newpin_hash[SHA1_DIGEST_LENGTH]; 179247e946e7SWyllys Ingersoll CK_RV rc; 179347e946e7SWyllys Ingersoll TSS_HKEY hSRK; 179447e946e7SWyllys Ingersoll 179547e946e7SWyllys Ingersoll if (!sess) { 179647e946e7SWyllys Ingersoll return (CKR_SESSION_HANDLE_INVALID); 179747e946e7SWyllys Ingersoll } 179847e946e7SWyllys Ingersoll 179947e946e7SWyllys Ingersoll if ((rc = compute_sha(pOldPin, ulOldPinLen, oldpin_hash))) { 180047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 180147e946e7SWyllys Ingersoll } 180247e946e7SWyllys Ingersoll if ((rc = compute_sha(pNewPin, ulNewPinLen, newpin_hash))) { 180347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 180447e946e7SWyllys Ingersoll } 180547e946e7SWyllys Ingersoll 180647e946e7SWyllys Ingersoll if (token_load_srk(sess->hContext, &hSRK)) { 180747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 180847e946e7SWyllys Ingersoll } 180947e946e7SWyllys Ingersoll 181047e946e7SWyllys Ingersoll /* 181147e946e7SWyllys Ingersoll * From the PKCS#11 2.20 spec: "C_SetPIN modifies the PIN of 181247e946e7SWyllys Ingersoll * the user that is currently logged in, or the CKU_USER PIN 181347e946e7SWyllys Ingersoll * if the session is not logged in." 181447e946e7SWyllys Ingersoll * A non R/W session fails with CKR_SESSION_READ_ONLY. 181547e946e7SWyllys Ingersoll */ 181647e946e7SWyllys Ingersoll if (sess->session_info.state == CKS_RW_USER_FUNCTIONS || 181747e946e7SWyllys Ingersoll sess->session_info.state == CKS_RW_PUBLIC_SESSION) { 181847e946e7SWyllys Ingersoll if (not_initialized) { 181947e946e7SWyllys Ingersoll if (memcmp(oldpin_hash, default_user_pin_sha, 182047e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 182147e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 182247e946e7SWyllys Ingersoll } 182347e946e7SWyllys Ingersoll 182447e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_USER, newpin_hash, 182547e946e7SWyllys Ingersoll ulNewPinLen))) { 182647e946e7SWyllys Ingersoll return (rc); 182747e946e7SWyllys Ingersoll } 182847e946e7SWyllys Ingersoll 182947e946e7SWyllys Ingersoll if ((rc = token_create_private_tree(sess->hContext, 183047e946e7SWyllys Ingersoll newpin_hash))) { 183147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 183247e946e7SWyllys Ingersoll } 183347e946e7SWyllys Ingersoll 183447e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 183547e946e7SWyllys Ingersoll ~(CKF_USER_PIN_TO_BE_CHANGED); 183647e946e7SWyllys Ingersoll nv_token_data->token_info.flags |= 183747e946e7SWyllys Ingersoll CKF_USER_PIN_INITIALIZED; 183847e946e7SWyllys Ingersoll 183947e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 184047e946e7SWyllys Ingersoll ~(CKF_USER_PIN_TO_BE_CHANGED); 184147e946e7SWyllys Ingersoll nv_token_data->token_info.flags |= 184247e946e7SWyllys Ingersoll CKF_USER_PIN_INITIALIZED; 184347e946e7SWyllys Ingersoll 184447e946e7SWyllys Ingersoll return (save_token_data(nv_token_data)); 184547e946e7SWyllys Ingersoll } 184647e946e7SWyllys Ingersoll 184747e946e7SWyllys Ingersoll if (sess->session_info.state == CKS_RW_USER_FUNCTIONS) { 184847e946e7SWyllys Ingersoll /* if we're already logged in, just verify the hash */ 184947e946e7SWyllys Ingersoll if (memcmp(current_user_pin_sha, oldpin_hash, 185047e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 185147e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 185247e946e7SWyllys Ingersoll } 185347e946e7SWyllys Ingersoll } else { 185447e946e7SWyllys Ingersoll if ((rc = verify_user_pin(sess->hContext, 185547e946e7SWyllys Ingersoll oldpin_hash))) { 185647e946e7SWyllys Ingersoll return (rc); 185747e946e7SWyllys Ingersoll } 185847e946e7SWyllys Ingersoll } 185947e946e7SWyllys Ingersoll 186047e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_USER, newpin_hash, 186147e946e7SWyllys Ingersoll ulNewPinLen))) 186247e946e7SWyllys Ingersoll return (rc); 186347e946e7SWyllys Ingersoll 186447e946e7SWyllys Ingersoll /* change the auth on the TSS object */ 186547e946e7SWyllys Ingersoll if (tss_change_auth(sess->hContext, 186647e946e7SWyllys Ingersoll hPrivateLeafKey, hPrivateRootKey, 186747e946e7SWyllys Ingersoll privateLeafKeyUUID, privateRootKeyUUID, 186847e946e7SWyllys Ingersoll newpin_hash)) 186947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 187047e946e7SWyllys Ingersoll 187147e946e7SWyllys Ingersoll } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) { 187247e946e7SWyllys Ingersoll if (not_initialized) { 187347e946e7SWyllys Ingersoll if (memcmp(default_so_pin_sha, oldpin_hash, 187447e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 187547e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 187647e946e7SWyllys Ingersoll 187747e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_SO, 187847e946e7SWyllys Ingersoll newpin_hash, ulNewPinLen))) 187947e946e7SWyllys Ingersoll return (rc); 188047e946e7SWyllys Ingersoll 188147e946e7SWyllys Ingersoll if ((rc = token_create_public_tree(sess->hContext, 188247e946e7SWyllys Ingersoll newpin_hash))) 188347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 188447e946e7SWyllys Ingersoll 188547e946e7SWyllys Ingersoll nv_token_data->token_info.flags &= 188647e946e7SWyllys Ingersoll ~(CKF_SO_PIN_TO_BE_CHANGED); 188747e946e7SWyllys Ingersoll 188847e946e7SWyllys Ingersoll return (save_token_data(nv_token_data)); 188947e946e7SWyllys Ingersoll } 189047e946e7SWyllys Ingersoll 189147e946e7SWyllys Ingersoll if (memcmp(current_so_pin_sha, oldpin_hash, 189247e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) 189347e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 189447e946e7SWyllys Ingersoll 189547e946e7SWyllys Ingersoll if ((rc = check_pin_properties(CKU_SO, newpin_hash, 189647e946e7SWyllys Ingersoll ulNewPinLen))) 189747e946e7SWyllys Ingersoll return (rc); 189847e946e7SWyllys Ingersoll 189947e946e7SWyllys Ingersoll /* change auth on the SO's leaf key */ 190047e946e7SWyllys Ingersoll if (tss_change_auth(sess->hContext, 190147e946e7SWyllys Ingersoll hPublicLeafKey, hPublicRootKey, 190247e946e7SWyllys Ingersoll publicLeafKeyUUID, publicRootKeyUUID, 190347e946e7SWyllys Ingersoll newpin_hash)) 190447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 190547e946e7SWyllys Ingersoll 190647e946e7SWyllys Ingersoll } else { 190747e946e7SWyllys Ingersoll rc = CKR_SESSION_READ_ONLY; 190847e946e7SWyllys Ingersoll } 190947e946e7SWyllys Ingersoll 191047e946e7SWyllys Ingersoll return (rc); 191147e946e7SWyllys Ingersoll } 191247e946e7SWyllys Ingersoll 191347e946e7SWyllys Ingersoll /* only called at token init time */ 191447e946e7SWyllys Ingersoll CK_RV 191547e946e7SWyllys Ingersoll token_specific_verify_so_pin(TSS_HCONTEXT hContext, CK_CHAR_PTR pPin, 191647e946e7SWyllys Ingersoll CK_ULONG ulPinLen) 191747e946e7SWyllys Ingersoll { 191847e946e7SWyllys Ingersoll CK_BYTE hash_sha[SHA1_DIGEST_LENGTH]; 191947e946e7SWyllys Ingersoll CK_RV rc; 192047e946e7SWyllys Ingersoll TSS_RESULT result; 192147e946e7SWyllys Ingersoll TSS_HKEY hSRK; 192247e946e7SWyllys Ingersoll 192347e946e7SWyllys Ingersoll if ((rc = compute_sha(pPin, ulPinLen, hash_sha))) { 192447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 192547e946e7SWyllys Ingersoll } 192647e946e7SWyllys Ingersoll if ((rc = token_load_srk(hContext, &hSRK))) { 192747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 192847e946e7SWyllys Ingersoll } 192947e946e7SWyllys Ingersoll 193047e946e7SWyllys Ingersoll /* 193147e946e7SWyllys Ingersoll * TRYME INSTEAD: 193247e946e7SWyllys Ingersoll * - find publicRootKeyUUID 193347e946e7SWyllys Ingersoll * - Load publicRootKey by UUID (SRK parent) 193447e946e7SWyllys Ingersoll * - find publicLeafKeyUUID 193547e946e7SWyllys Ingersoll * - Load publicLeafKey by UUID (publicRootKey parent) 193647e946e7SWyllys Ingersoll * - set password policy on publicLeafKey 193747e946e7SWyllys Ingersoll */ 193847e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicRootKeyUUID) && 193947e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_ROOT_KEY_ID, &publicRootKeyUUID)) { 194047e946e7SWyllys Ingersoll /* 194147e946e7SWyllys Ingersoll * The SO hasn't set her PIN yet, compare the 194247e946e7SWyllys Ingersoll * login pin with the hard-coded value. 194347e946e7SWyllys Ingersoll */ 194447e946e7SWyllys Ingersoll if (memcmp(default_so_pin_sha, hash_sha, 194547e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH)) { 194647e946e7SWyllys Ingersoll return (CKR_PIN_INCORRECT); 194747e946e7SWyllys Ingersoll } 194847e946e7SWyllys Ingersoll return (CKR_OK); 194947e946e7SWyllys Ingersoll } 195047e946e7SWyllys Ingersoll 195147e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 195247e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicRootKeyUUID, &hPublicRootKey); 195347e946e7SWyllys Ingersoll 195447e946e7SWyllys Ingersoll if (result) 195547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 195647e946e7SWyllys Ingersoll 195747e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(hPublicRootKey, hSRK); 195847e946e7SWyllys Ingersoll if (result) 195947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 196047e946e7SWyllys Ingersoll 196147e946e7SWyllys Ingersoll if (local_uuid_is_null(&publicLeafKeyUUID) && 196247e946e7SWyllys Ingersoll find_uuid(TPMTOK_PUBLIC_LEAF_KEY_ID, &publicLeafKeyUUID)) 196347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 196447e946e7SWyllys Ingersoll 196547e946e7SWyllys Ingersoll result = Tspi_Context_GetKeyByUUID(hContext, 196647e946e7SWyllys Ingersoll TSS_PS_TYPE_USER, publicLeafKeyUUID, &hPublicLeafKey); 196747e946e7SWyllys Ingersoll if (result) 196847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 196947e946e7SWyllys Ingersoll 1970*ab8176c2SWyllys Ingersoll result = tss_assign_secret_key_policy(hContext, TSS_POLICY_USAGE, 1971*ab8176c2SWyllys Ingersoll hPublicLeafKey, hash_sha); 197247e946e7SWyllys Ingersoll if (result) 197347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 197447e946e7SWyllys Ingersoll 197547e946e7SWyllys Ingersoll result = Tspi_Key_LoadKey(hPublicLeafKey, hPublicRootKey); 197647e946e7SWyllys Ingersoll if (result) 197747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 197847e946e7SWyllys Ingersoll 197947e946e7SWyllys Ingersoll /* If the hash given is wrong, the verify will fail */ 198047e946e7SWyllys Ingersoll if ((rc = token_verify_pin(hContext, hPublicLeafKey))) { 198147e946e7SWyllys Ingersoll return (rc); 198247e946e7SWyllys Ingersoll } 198347e946e7SWyllys Ingersoll 198447e946e7SWyllys Ingersoll return (CKR_OK); 198547e946e7SWyllys Ingersoll } 198647e946e7SWyllys Ingersoll 198747e946e7SWyllys Ingersoll CK_RV 1988*ab8176c2SWyllys Ingersoll token_specific_final(TSS_HCONTEXT hContext) 198947e946e7SWyllys Ingersoll { 1990*ab8176c2SWyllys Ingersoll if (hPublicRootKey != NULL_HKEY) { 1991*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicRootKey); 1992*ab8176c2SWyllys Ingersoll hPublicRootKey = NULL_HKEY; 1993*ab8176c2SWyllys Ingersoll } 1994*ab8176c2SWyllys Ingersoll if (hPublicLeafKey != NULL_HKEY) { 1995*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPublicLeafKey); 1996*ab8176c2SWyllys Ingersoll hPublicLeafKey = NULL_HKEY; 1997*ab8176c2SWyllys Ingersoll } 1998*ab8176c2SWyllys Ingersoll if (hPrivateRootKey != NULL_HKEY) { 1999*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateRootKey); 2000*ab8176c2SWyllys Ingersoll hPrivateRootKey = NULL_HKEY; 2001*ab8176c2SWyllys Ingersoll } 2002*ab8176c2SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 2003*ab8176c2SWyllys Ingersoll Tspi_Context_CloseObject(hContext, hPrivateLeafKey); 2004*ab8176c2SWyllys Ingersoll hPrivateLeafKey = NULL_HKEY; 2005*ab8176c2SWyllys Ingersoll } 200647e946e7SWyllys Ingersoll return (CKR_OK); 200747e946e7SWyllys Ingersoll } 200847e946e7SWyllys Ingersoll 200947e946e7SWyllys Ingersoll /* 201047e946e7SWyllys Ingersoll * Wrap the 20 bytes of auth data and store in an attribute of the two 201147e946e7SWyllys Ingersoll * keys. 201247e946e7SWyllys Ingersoll */ 201347e946e7SWyllys Ingersoll static CK_RV 201447e946e7SWyllys Ingersoll token_wrap_auth_data(TSS_HCONTEXT hContext, 201547e946e7SWyllys Ingersoll CK_BYTE *authData, TEMPLATE *publ_tmpl, 201647e946e7SWyllys Ingersoll TEMPLATE *priv_tmpl) 201747e946e7SWyllys Ingersoll { 201847e946e7SWyllys Ingersoll CK_RV rc; 201947e946e7SWyllys Ingersoll CK_ATTRIBUTE *new_attr; 202047e946e7SWyllys Ingersoll 202147e946e7SWyllys Ingersoll TSS_RESULT ret; 202247e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 202347e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 202447e946e7SWyllys Ingersoll BYTE *blob; 202547e946e7SWyllys Ingersoll UINT32 blob_size; 202647e946e7SWyllys Ingersoll 202747e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && (hPublicLeafKey == NULL_HKEY)) { 202847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 202947e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 203047e946e7SWyllys Ingersoll hParentKey = hPublicLeafKey; 203147e946e7SWyllys Ingersoll } else { 203247e946e7SWyllys Ingersoll hParentKey = hPrivateLeafKey; 203347e946e7SWyllys Ingersoll } 203447e946e7SWyllys Ingersoll 203547e946e7SWyllys Ingersoll /* create the encrypted data object */ 203647e946e7SWyllys Ingersoll if ((ret = Tspi_Context_CreateObject(hContext, 203747e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 203847e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 203947e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 204047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 204147e946e7SWyllys Ingersoll } 204247e946e7SWyllys Ingersoll 204347e946e7SWyllys Ingersoll if ((ret = Tspi_Data_Bind(hEncData, hParentKey, SHA1_DIGEST_LENGTH, 204447e946e7SWyllys Ingersoll authData))) { 204547e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 204647e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 204747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 204847e946e7SWyllys Ingersoll } 204947e946e7SWyllys Ingersoll 205047e946e7SWyllys Ingersoll /* pull the encrypted data out of the encrypted data object */ 205147e946e7SWyllys Ingersoll if ((ret = Tspi_GetAttribData(hEncData, TSS_TSPATTRIB_ENCDATA_BLOB, 205247e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, &blob_size, &blob))) { 205347e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 205447e946e7SWyllys Ingersoll ret, Trspi_Error_String(ret)); 205547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 205647e946e7SWyllys Ingersoll } 205747e946e7SWyllys Ingersoll 205847e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, blob_size, 205947e946e7SWyllys Ingersoll &new_attr))) { 206047e946e7SWyllys Ingersoll return (rc); 206147e946e7SWyllys Ingersoll } 206247e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, new_attr); 206347e946e7SWyllys Ingersoll 206447e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_ENC_AUTHDATA, blob, 206547e946e7SWyllys Ingersoll blob_size, &new_attr))) { 206647e946e7SWyllys Ingersoll return (rc); 206747e946e7SWyllys Ingersoll } 206847e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, new_attr); 206947e946e7SWyllys Ingersoll 207047e946e7SWyllys Ingersoll return (rc); 207147e946e7SWyllys Ingersoll } 207247e946e7SWyllys Ingersoll 207347e946e7SWyllys Ingersoll static CK_RV 207447e946e7SWyllys Ingersoll token_unwrap_auth_data(TSS_HCONTEXT hContext, CK_BYTE *encAuthData, 207547e946e7SWyllys Ingersoll CK_ULONG encAuthDataLen, TSS_HKEY hKey, 207647e946e7SWyllys Ingersoll BYTE **authData) 207747e946e7SWyllys Ingersoll { 207847e946e7SWyllys Ingersoll TSS_RESULT result; 207947e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 208047e946e7SWyllys Ingersoll BYTE *buf; 208147e946e7SWyllys Ingersoll UINT32 buf_size; 208247e946e7SWyllys Ingersoll 208347e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 208447e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 208547e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 208647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 208747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 208847e946e7SWyllys Ingersoll } 208947e946e7SWyllys Ingersoll 209047e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribData(hEncData, 209147e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB, 209247e946e7SWyllys Ingersoll encAuthDataLen, encAuthData))) { 209347e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 209447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 209547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 209647e946e7SWyllys Ingersoll } 209747e946e7SWyllys Ingersoll 209847e946e7SWyllys Ingersoll /* unbind the data, receiving the plaintext back */ 209947e946e7SWyllys Ingersoll if ((result = Tspi_Data_Unbind(hEncData, hKey, &buf_size, &buf))) { 210047e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 210147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 210247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 210347e946e7SWyllys Ingersoll } 210447e946e7SWyllys Ingersoll 210547e946e7SWyllys Ingersoll if (buf_size != SHA1_DIGEST_LENGTH) { 210647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 210747e946e7SWyllys Ingersoll } 210847e946e7SWyllys Ingersoll 210947e946e7SWyllys Ingersoll *authData = buf; 211047e946e7SWyllys Ingersoll 211147e946e7SWyllys Ingersoll return (CKR_OK); 211247e946e7SWyllys Ingersoll } 211347e946e7SWyllys Ingersoll 211447e946e7SWyllys Ingersoll CK_RV 211547e946e7SWyllys Ingersoll token_specific_rsa_generate_keypair( 211647e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 211747e946e7SWyllys Ingersoll TEMPLATE *publ_tmpl, 211847e946e7SWyllys Ingersoll TEMPLATE *priv_tmpl) 211947e946e7SWyllys Ingersoll { 212047e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr = NULL; 212147e946e7SWyllys Ingersoll CK_ULONG mod_bits = 0; 212247e946e7SWyllys Ingersoll CK_BBOOL flag; 212347e946e7SWyllys Ingersoll CK_RV rc; 212447e946e7SWyllys Ingersoll 212547e946e7SWyllys Ingersoll TSS_FLAG initFlags = 0; 212647e946e7SWyllys Ingersoll BYTE authHash[SHA1_DIGEST_LENGTH]; 212747e946e7SWyllys Ingersoll BYTE *authData = NULL; 212847e946e7SWyllys Ingersoll TSS_HKEY hKey = NULL_HKEY; 212947e946e7SWyllys Ingersoll TSS_HKEY hParentKey = NULL_HKEY; 213047e946e7SWyllys Ingersoll TSS_RESULT result; 213147e946e7SWyllys Ingersoll UINT32 ulBlobLen; 213247e946e7SWyllys Ingersoll BYTE *rgbBlob; 213347e946e7SWyllys Ingersoll 213447e946e7SWyllys Ingersoll /* Make sure the public exponent is usable */ 213547e946e7SWyllys Ingersoll if ((util_check_public_exponent(publ_tmpl))) { 213647e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCONSISTENT); 213747e946e7SWyllys Ingersoll } 213847e946e7SWyllys Ingersoll 213947e946e7SWyllys Ingersoll flag = template_attribute_find(publ_tmpl, CKA_MODULUS_BITS, &attr); 214047e946e7SWyllys Ingersoll if (!flag) { 214147e946e7SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 214247e946e7SWyllys Ingersoll } 214347e946e7SWyllys Ingersoll mod_bits = *(CK_ULONG *)attr->pValue; 214447e946e7SWyllys Ingersoll 214547e946e7SWyllys Ingersoll if ((initFlags = util_get_keysize_flag(mod_bits)) == 0) { 214647e946e7SWyllys Ingersoll return (CKR_KEY_SIZE_RANGE); 214747e946e7SWyllys Ingersoll } 214847e946e7SWyllys Ingersoll 214947e946e7SWyllys Ingersoll /* 215047e946e7SWyllys Ingersoll * If we're not logged in, hPrivateLeafKey and hPublicLeafKey 215147e946e7SWyllys Ingersoll * should be NULL. 215247e946e7SWyllys Ingersoll */ 215347e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && 215447e946e7SWyllys Ingersoll (hPublicLeafKey == NULL_HKEY)) { 215547e946e7SWyllys Ingersoll /* public session, wrap key with the PRK */ 215647e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 215747e946e7SWyllys Ingersoll TSS_KEY_NO_AUTHORIZATION | TSS_KEY_MIGRATABLE; 215847e946e7SWyllys Ingersoll 215947e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) { 216047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 216147e946e7SWyllys Ingersoll } 216247e946e7SWyllys Ingersoll 216347e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 216447e946e7SWyllys Ingersoll } else if (hPrivateLeafKey != NULL_HKEY) { 216547e946e7SWyllys Ingersoll /* logged in USER session */ 216647e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 216747e946e7SWyllys Ingersoll TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; 216847e946e7SWyllys Ingersoll 216947e946e7SWyllys Ingersoll /* get a random SHA1 hash for the auth data */ 217047e946e7SWyllys Ingersoll if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { 217147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 217247e946e7SWyllys Ingersoll } 217347e946e7SWyllys Ingersoll 217447e946e7SWyllys Ingersoll authData = authHash; 217547e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 217647e946e7SWyllys Ingersoll } else { 217747e946e7SWyllys Ingersoll /* logged in SO session */ 217847e946e7SWyllys Ingersoll initFlags |= TSS_KEY_TYPE_LEGACY | 217947e946e7SWyllys Ingersoll TSS_KEY_AUTHORIZATION | TSS_KEY_MIGRATABLE; 218047e946e7SWyllys Ingersoll 218147e946e7SWyllys Ingersoll /* get a random SHA1 hash for the auth data */ 218247e946e7SWyllys Ingersoll if ((rc = token_rng(hContext, authHash, SHA1_DIGEST_LENGTH))) { 218347e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 218447e946e7SWyllys Ingersoll } 218547e946e7SWyllys Ingersoll 218647e946e7SWyllys Ingersoll authData = authHash; 218747e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 218847e946e7SWyllys Ingersoll } 218947e946e7SWyllys Ingersoll 219047e946e7SWyllys Ingersoll if ((result = tss_generate_key(hContext, initFlags, authData, 219147e946e7SWyllys Ingersoll hParentKey, &hKey))) { 219247e946e7SWyllys Ingersoll return (result); 219347e946e7SWyllys Ingersoll } 219447e946e7SWyllys Ingersoll 219547e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB, 219647e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYBLOB_BLOB, &ulBlobLen, &rgbBlob))) { 219747e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 219847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 219947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 220047e946e7SWyllys Ingersoll } 220147e946e7SWyllys Ingersoll 220247e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, 220347e946e7SWyllys Ingersoll ulBlobLen, &attr))) { 220447e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 220547e946e7SWyllys Ingersoll return (rc); 220647e946e7SWyllys Ingersoll } 220747e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, attr); 220847e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_IBM_OPAQUE, rgbBlob, 220947e946e7SWyllys Ingersoll ulBlobLen, &attr))) { 221047e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 221147e946e7SWyllys Ingersoll return (rc); 221247e946e7SWyllys Ingersoll } 221347e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, attr); 221447e946e7SWyllys Ingersoll 221547e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 221647e946e7SWyllys Ingersoll 221747e946e7SWyllys Ingersoll /* grab the public key to put into the public key object */ 221847e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 221947e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &ulBlobLen, &rgbBlob))) { 222047e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 222147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 222247e946e7SWyllys Ingersoll return (result); 222347e946e7SWyllys Ingersoll } 222447e946e7SWyllys Ingersoll 222547e946e7SWyllys Ingersoll /* add the public key blob to the object template */ 222647e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { 222747e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 222847e946e7SWyllys Ingersoll return (rc); 222947e946e7SWyllys Ingersoll } 223047e946e7SWyllys Ingersoll (void) template_update_attribute(publ_tmpl, attr); 223147e946e7SWyllys Ingersoll 223247e946e7SWyllys Ingersoll /* add the public key blob to the object template */ 223347e946e7SWyllys Ingersoll if ((rc = build_attribute(CKA_MODULUS, rgbBlob, ulBlobLen, &attr))) { 223447e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 223547e946e7SWyllys Ingersoll return (rc); 223647e946e7SWyllys Ingersoll } 223747e946e7SWyllys Ingersoll (void) template_update_attribute(priv_tmpl, attr); 223847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, rgbBlob); 223947e946e7SWyllys Ingersoll 224047e946e7SWyllys Ingersoll /* wrap the authdata and put it into an object */ 224147e946e7SWyllys Ingersoll if (authData != NULL) { 224247e946e7SWyllys Ingersoll rc = token_wrap_auth_data(hContext, authData, publ_tmpl, 224347e946e7SWyllys Ingersoll priv_tmpl); 224447e946e7SWyllys Ingersoll } 224547e946e7SWyllys Ingersoll 224647e946e7SWyllys Ingersoll return (rc); 224747e946e7SWyllys Ingersoll } 224847e946e7SWyllys Ingersoll 224947e946e7SWyllys Ingersoll static CK_RV 225047e946e7SWyllys Ingersoll token_rsa_load_key( 225147e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 225247e946e7SWyllys Ingersoll OBJECT *key_obj, 225347e946e7SWyllys Ingersoll TSS_HKEY *phKey) 225447e946e7SWyllys Ingersoll { 225547e946e7SWyllys Ingersoll TSS_RESULT result; 225647e946e7SWyllys Ingersoll TSS_HPOLICY hPolicy = NULL_HPOLICY; 225747e946e7SWyllys Ingersoll TSS_HKEY hParentKey; 225847e946e7SWyllys Ingersoll BYTE *authData = NULL; 225947e946e7SWyllys Ingersoll CK_ATTRIBUTE *attr; 226047e946e7SWyllys Ingersoll CK_RV rc; 226147e946e7SWyllys Ingersoll CK_OBJECT_HANDLE handle; 2262*ab8176c2SWyllys Ingersoll CK_ULONG class; 226347e946e7SWyllys Ingersoll 226447e946e7SWyllys Ingersoll if (hPrivateLeafKey != NULL_HKEY) { 226547e946e7SWyllys Ingersoll hParentKey = hPrivateRootKey; 226647e946e7SWyllys Ingersoll } else { 226747e946e7SWyllys Ingersoll if ((result = token_load_public_root_key(hContext))) 226847e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 226947e946e7SWyllys Ingersoll 227047e946e7SWyllys Ingersoll hParentKey = hPublicRootKey; 227147e946e7SWyllys Ingersoll } 227247e946e7SWyllys Ingersoll 2273*ab8176c2SWyllys Ingersoll *phKey = NULL; 2274*ab8176c2SWyllys Ingersoll if (template_attribute_find(key_obj->template, CKA_CLASS, 2275*ab8176c2SWyllys Ingersoll &attr) == FALSE) { 2276*ab8176c2SWyllys Ingersoll return (CKR_TEMPLATE_INCOMPLETE); 2277*ab8176c2SWyllys Ingersoll } 2278*ab8176c2SWyllys Ingersoll class = *((CK_ULONG *)attr->pValue); 2279*ab8176c2SWyllys Ingersoll 2280*ab8176c2SWyllys Ingersoll rc = template_attribute_find(key_obj->template, 2281*ab8176c2SWyllys Ingersoll CKA_IBM_OPAQUE, &attr); 2282*ab8176c2SWyllys Ingersoll /* 2283*ab8176c2SWyllys Ingersoll * A public key cannot use the OPAQUE data attribute so they 2284*ab8176c2SWyllys Ingersoll * must be created in software. A private key may not yet 2285*ab8176c2SWyllys Ingersoll * have its "opaque" data defined and needs to be created 2286*ab8176c2SWyllys Ingersoll * and loaded so it can be used inside the TPM. 2287*ab8176c2SWyllys Ingersoll */ 2288*ab8176c2SWyllys Ingersoll if (class == CKO_PUBLIC_KEY || rc == FALSE) { 228947e946e7SWyllys Ingersoll rc = object_mgr_find_in_map2(hContext, key_obj, &handle); 229047e946e7SWyllys Ingersoll if (rc != CKR_OK) 229147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 229247e946e7SWyllys Ingersoll 229347e946e7SWyllys Ingersoll if ((rc = token_load_key(hContext, 229447e946e7SWyllys Ingersoll handle, hParentKey, NULL, phKey))) { 229547e946e7SWyllys Ingersoll return (rc); 229647e946e7SWyllys Ingersoll } 2297*ab8176c2SWyllys Ingersoll } 2298*ab8176c2SWyllys Ingersoll /* 2299*ab8176c2SWyllys Ingersoll * If this is a private key, get the blob and load it in the TPM. 2300*ab8176c2SWyllys Ingersoll * If it is public, the key is already loaded in software. 2301*ab8176c2SWyllys Ingersoll */ 2302*ab8176c2SWyllys Ingersoll if (class == CKO_PRIVATE_KEY) { 2303*ab8176c2SWyllys Ingersoll /* If we already have a handle, just load it */ 2304*ab8176c2SWyllys Ingersoll if (*phKey != NULL) { 2305*ab8176c2SWyllys Ingersoll result = Tspi_Key_LoadKey(*phKey, hParentKey); 2306*ab8176c2SWyllys Ingersoll if (result) { 2307*ab8176c2SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByBlob: " 2308*ab8176c2SWyllys Ingersoll "0x%0x - %s", 2309*ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 2310*ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 2311*ab8176c2SWyllys Ingersoll } 2312*ab8176c2SWyllys Ingersoll } else { 231347e946e7SWyllys Ingersoll /* try again to get the CKA_IBM_OPAQUE attr */ 231447e946e7SWyllys Ingersoll if ((rc = template_attribute_find(key_obj->template, 231547e946e7SWyllys Ingersoll CKA_IBM_OPAQUE, &attr)) == FALSE) { 231647e946e7SWyllys Ingersoll return (rc); 231747e946e7SWyllys Ingersoll } 231847e946e7SWyllys Ingersoll if ((result = Tspi_Context_LoadKeyByBlob(hContext, 2319*ab8176c2SWyllys Ingersoll hParentKey, attr->ulValueLen, attr->pValue, 2320*ab8176c2SWyllys Ingersoll phKey))) { 2321*ab8176c2SWyllys Ingersoll stlogit("Tspi_Context_LoadKeyByBlob: " 2322*ab8176c2SWyllys Ingersoll "0x%0x - %s", 232347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 232447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 232547e946e7SWyllys Ingersoll } 2326*ab8176c2SWyllys Ingersoll } 2327*ab8176c2SWyllys Ingersoll } 232847e946e7SWyllys Ingersoll 232947e946e7SWyllys Ingersoll /* auth data may be required */ 233047e946e7SWyllys Ingersoll if (template_attribute_find(key_obj->template, CKA_ENC_AUTHDATA, 233147e946e7SWyllys Ingersoll &attr) == TRUE && attr) { 233247e946e7SWyllys Ingersoll if ((hPrivateLeafKey == NULL_HKEY) && 233347e946e7SWyllys Ingersoll (hPublicLeafKey == NULL_HKEY)) { 233447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 233547e946e7SWyllys Ingersoll } else if (hPublicLeafKey != NULL_HKEY) { 233647e946e7SWyllys Ingersoll hParentKey = hPublicLeafKey; 233747e946e7SWyllys Ingersoll } else { 233847e946e7SWyllys Ingersoll hParentKey = hPrivateLeafKey; 233947e946e7SWyllys Ingersoll } 234047e946e7SWyllys Ingersoll 234147e946e7SWyllys Ingersoll if ((result = token_unwrap_auth_data(hContext, 2342*ab8176c2SWyllys Ingersoll attr->pValue, attr->ulValueLen, 2343*ab8176c2SWyllys Ingersoll hParentKey, &authData))) { 234447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 234547e946e7SWyllys Ingersoll } 234647e946e7SWyllys Ingersoll 234747e946e7SWyllys Ingersoll if ((result = Tspi_GetPolicyObject(*phKey, 234847e946e7SWyllys Ingersoll TSS_POLICY_USAGE, &hPolicy))) { 234947e946e7SWyllys Ingersoll stlogit("Tspi_GetPolicyObject: 0x%0x - %s", 235047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 235147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 235247e946e7SWyllys Ingersoll } 235347e946e7SWyllys Ingersoll 235447e946e7SWyllys Ingersoll /* 235547e946e7SWyllys Ingersoll * If the policy handle returned is the same as the 235647e946e7SWyllys Ingersoll * context's default policy, then a new policy must 235747e946e7SWyllys Ingersoll * be created and assigned to the key. Otherwise, just set the 235847e946e7SWyllys Ingersoll * secret in the policy. 235947e946e7SWyllys Ingersoll */ 236047e946e7SWyllys Ingersoll if (hPolicy == hDefaultPolicy) { 236147e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 236247e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 236347e946e7SWyllys Ingersoll &hPolicy))) { 236447e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: " 236547e946e7SWyllys Ingersoll "0x%0x - %s", 236647e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 236747e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 236847e946e7SWyllys Ingersoll } 236947e946e7SWyllys Ingersoll 237047e946e7SWyllys Ingersoll if ((result = Tspi_Policy_SetSecret(hPolicy, 237147e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, 237247e946e7SWyllys Ingersoll SHA1_DIGEST_LENGTH, authData))) { 237347e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: " 237447e946e7SWyllys Ingersoll "0x%0x - %s", 237547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 237647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 237747e946e7SWyllys Ingersoll } 237847e946e7SWyllys Ingersoll 237947e946e7SWyllys Ingersoll if ((result = Tspi_Policy_AssignToObject(hPolicy, 238047e946e7SWyllys Ingersoll *phKey))) { 238147e946e7SWyllys Ingersoll stlogit("Tspi_Policy_AssignToObject: " 238247e946e7SWyllys Ingersoll "0x%0x - %s", 238347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 238447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 238547e946e7SWyllys Ingersoll } 238647e946e7SWyllys Ingersoll } else if ((result = Tspi_Policy_SetSecret(hPolicy, 238747e946e7SWyllys Ingersoll TSS_SECRET_MODE_SHA1, SHA1_DIGEST_LENGTH, authData))) { 238847e946e7SWyllys Ingersoll stlogit("Tspi_Policy_SetSecret: 0x%0x - %s", 238947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 239047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 239147e946e7SWyllys Ingersoll } 239247e946e7SWyllys Ingersoll 239347e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, authData); 239447e946e7SWyllys Ingersoll } 239547e946e7SWyllys Ingersoll 239647e946e7SWyllys Ingersoll return (CKR_OK); 239747e946e7SWyllys Ingersoll } 239847e946e7SWyllys Ingersoll 239947e946e7SWyllys Ingersoll CK_RV 240047e946e7SWyllys Ingersoll tpm_decrypt_data( 240147e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 240247e946e7SWyllys Ingersoll TSS_HKEY hKey, 240347e946e7SWyllys Ingersoll CK_BYTE * in_data, 240447e946e7SWyllys Ingersoll CK_ULONG in_data_len, 240547e946e7SWyllys Ingersoll CK_BYTE * out_data, 240647e946e7SWyllys Ingersoll CK_ULONG * out_data_len) 240747e946e7SWyllys Ingersoll { 240847e946e7SWyllys Ingersoll TSS_RESULT result; 240947e946e7SWyllys Ingersoll TSS_HENCDATA hEncData = NULL_HENCDATA; 241047e946e7SWyllys Ingersoll UINT32 buf_size = 0, modLen; 241147e946e7SWyllys Ingersoll BYTE *buf = NULL, *modulus = NULL; 241247e946e7SWyllys Ingersoll CK_ULONG chunklen, remain, outlen; 241347e946e7SWyllys Ingersoll 241447e946e7SWyllys Ingersoll /* push the data into the encrypted data object */ 241547e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 241647e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 241747e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 241847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 241947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 242047e946e7SWyllys Ingersoll } 242147e946e7SWyllys Ingersoll 242247e946e7SWyllys Ingersoll /* 242347e946e7SWyllys Ingersoll * Figure out the modulus size so we can break the data 242447e946e7SWyllys Ingersoll * into smaller chunks if necessary. 242547e946e7SWyllys Ingersoll */ 242647e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 242747e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 242847e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 242947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 243047e946e7SWyllys Ingersoll return (result); 243147e946e7SWyllys Ingersoll } 243247e946e7SWyllys Ingersoll /* we don't need the actual modulus */ 243347e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 243447e946e7SWyllys Ingersoll 243547e946e7SWyllys Ingersoll chunklen = (in_data_len > modLen ? modLen : in_data_len); 243647e946e7SWyllys Ingersoll remain = in_data_len; 243747e946e7SWyllys Ingersoll outlen = 0; 243847e946e7SWyllys Ingersoll 243947e946e7SWyllys Ingersoll while (remain > 0) { 244047e946e7SWyllys Ingersoll if ((result = Tspi_SetAttribData(hEncData, 244147e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, 244247e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, 244347e946e7SWyllys Ingersoll chunklen, in_data))) { 244447e946e7SWyllys Ingersoll stlogit("Tspi_SetAttribData: 0x%0x - %s", 244547e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 244647e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 244747e946e7SWyllys Ingersoll } 244847e946e7SWyllys Ingersoll 244947e946e7SWyllys Ingersoll /* unbind the data, receiving the plaintext back */ 245047e946e7SWyllys Ingersoll if ((result = Tspi_Data_Unbind(hEncData, hKey, 245147e946e7SWyllys Ingersoll &buf_size, &buf))) { 245247e946e7SWyllys Ingersoll stlogit("Tspi_Data_Unbind: 0x%0x - %s", 245347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 245447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 245547e946e7SWyllys Ingersoll } 245647e946e7SWyllys Ingersoll 245747e946e7SWyllys Ingersoll if (*out_data_len < buf_size + outlen) { 245847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, buf); 245947e946e7SWyllys Ingersoll return (CKR_BUFFER_TOO_SMALL); 246047e946e7SWyllys Ingersoll } 246147e946e7SWyllys Ingersoll 246247e946e7SWyllys Ingersoll (void) memcpy(out_data + outlen, buf, buf_size); 246347e946e7SWyllys Ingersoll 246447e946e7SWyllys Ingersoll outlen += buf_size; 246547e946e7SWyllys Ingersoll in_data += chunklen; 246647e946e7SWyllys Ingersoll remain -= chunklen; 246747e946e7SWyllys Ingersoll 246847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, buf); 246947e946e7SWyllys Ingersoll if (chunklen > remain) 247047e946e7SWyllys Ingersoll chunklen = remain; 247147e946e7SWyllys Ingersoll } 247247e946e7SWyllys Ingersoll *out_data_len = outlen; 247347e946e7SWyllys Ingersoll return (CKR_OK); 247447e946e7SWyllys Ingersoll } 247547e946e7SWyllys Ingersoll 247647e946e7SWyllys Ingersoll CK_RV 247747e946e7SWyllys Ingersoll token_specific_rsa_decrypt( 247847e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 247947e946e7SWyllys Ingersoll CK_BYTE * in_data, 248047e946e7SWyllys Ingersoll CK_ULONG in_data_len, 248147e946e7SWyllys Ingersoll CK_BYTE * out_data, 248247e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 248347e946e7SWyllys Ingersoll OBJECT * key_obj) 248447e946e7SWyllys Ingersoll { 248547e946e7SWyllys Ingersoll CK_RV rc; 248647e946e7SWyllys Ingersoll TSS_HKEY hKey; 248747e946e7SWyllys Ingersoll 248847e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 248947e946e7SWyllys Ingersoll return (rc); 249047e946e7SWyllys Ingersoll } 249147e946e7SWyllys Ingersoll 249247e946e7SWyllys Ingersoll rc = tpm_decrypt_data(hContext, hKey, in_data, in_data_len, 249347e946e7SWyllys Ingersoll out_data, out_data_len); 249447e946e7SWyllys Ingersoll 249547e946e7SWyllys Ingersoll return (rc); 249647e946e7SWyllys Ingersoll } 249747e946e7SWyllys Ingersoll 249847e946e7SWyllys Ingersoll CK_RV 249947e946e7SWyllys Ingersoll token_specific_rsa_verify( 250047e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 250147e946e7SWyllys Ingersoll CK_BYTE * in_data, 250247e946e7SWyllys Ingersoll CK_ULONG in_data_len, 250347e946e7SWyllys Ingersoll CK_BYTE * sig, 250447e946e7SWyllys Ingersoll CK_ULONG sig_len, 250547e946e7SWyllys Ingersoll OBJECT * key_obj) 250647e946e7SWyllys Ingersoll { 250747e946e7SWyllys Ingersoll TSS_RESULT result; 250847e946e7SWyllys Ingersoll TSS_HHASH hHash; 250947e946e7SWyllys Ingersoll TSS_HKEY hKey; 251047e946e7SWyllys Ingersoll CK_RV rc; 251147e946e7SWyllys Ingersoll 251247e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 251347e946e7SWyllys Ingersoll return (rc); 251447e946e7SWyllys Ingersoll } 251547e946e7SWyllys Ingersoll 251647e946e7SWyllys Ingersoll /* Create the hash object we'll use to sign */ 251747e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 251847e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { 251947e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 252047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 252147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 252247e946e7SWyllys Ingersoll } 252347e946e7SWyllys Ingersoll 252447e946e7SWyllys Ingersoll /* Insert the data into the hash object */ 252547e946e7SWyllys Ingersoll if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, 252647e946e7SWyllys Ingersoll in_data))) { 252747e946e7SWyllys Ingersoll stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", 252847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 252947e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 253047e946e7SWyllys Ingersoll } 253147e946e7SWyllys Ingersoll 253247e946e7SWyllys Ingersoll /* Verify */ 253347e946e7SWyllys Ingersoll result = Tspi_Hash_VerifySignature(hHash, hKey, sig_len, sig); 253447e946e7SWyllys Ingersoll if (result != TSS_SUCCESS && 253547e946e7SWyllys Ingersoll TPMTOK_TSS_ERROR_CODE(result) != TSS_E_FAIL) { 253647e946e7SWyllys Ingersoll stlogit("Tspi_Hash_VerifySignature: 0x%0x - %s", 253747e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 253847e946e7SWyllys Ingersoll } 253947e946e7SWyllys Ingersoll 254047e946e7SWyllys Ingersoll if (TPMTOK_TSS_ERROR_CODE(result) == TSS_E_FAIL) { 254147e946e7SWyllys Ingersoll rc = CKR_SIGNATURE_INVALID; 254247e946e7SWyllys Ingersoll } else { 254347e946e7SWyllys Ingersoll rc = CKR_OK; 254447e946e7SWyllys Ingersoll } 254547e946e7SWyllys Ingersoll 254647e946e7SWyllys Ingersoll return (rc); 254747e946e7SWyllys Ingersoll } 254847e946e7SWyllys Ingersoll 254947e946e7SWyllys Ingersoll CK_RV 255047e946e7SWyllys Ingersoll token_specific_rsa_sign( 255147e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 255247e946e7SWyllys Ingersoll CK_BYTE * in_data, 255347e946e7SWyllys Ingersoll CK_ULONG in_data_len, 255447e946e7SWyllys Ingersoll CK_BYTE * out_data, 255547e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 255647e946e7SWyllys Ingersoll OBJECT * key_obj) 255747e946e7SWyllys Ingersoll { 255847e946e7SWyllys Ingersoll TSS_RESULT result; 255947e946e7SWyllys Ingersoll TSS_HHASH hHash; 256047e946e7SWyllys Ingersoll BYTE *sig; 256147e946e7SWyllys Ingersoll UINT32 sig_len; 256247e946e7SWyllys Ingersoll TSS_HKEY hKey; 256347e946e7SWyllys Ingersoll CK_RV rc; 256447e946e7SWyllys Ingersoll 256547e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 256647e946e7SWyllys Ingersoll return (rc); 256747e946e7SWyllys Ingersoll } 256847e946e7SWyllys Ingersoll 256947e946e7SWyllys Ingersoll /* Create the hash object we'll use to sign */ 257047e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 257147e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &hHash))) { 257247e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 257347e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 257447e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 257547e946e7SWyllys Ingersoll } 257647e946e7SWyllys Ingersoll 257747e946e7SWyllys Ingersoll /* Insert the data into the hash object */ 257847e946e7SWyllys Ingersoll if ((result = Tspi_Hash_SetHashValue(hHash, in_data_len, 257947e946e7SWyllys Ingersoll in_data))) { 258047e946e7SWyllys Ingersoll stlogit("Tspi_Hash_SetHashValue: 0x%0x - %s", 258147e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 258247e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 258347e946e7SWyllys Ingersoll } 258447e946e7SWyllys Ingersoll 258547e946e7SWyllys Ingersoll /* Sign */ 258647e946e7SWyllys Ingersoll if ((result = Tspi_Hash_Sign(hHash, hKey, &sig_len, &sig))) { 258747e946e7SWyllys Ingersoll stlogit("Tspi_Hash_Sign: 0x%0x - %s", 258847e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 2589*ab8176c2SWyllys Ingersoll return (CKR_DATA_LEN_RANGE); 259047e946e7SWyllys Ingersoll } 259147e946e7SWyllys Ingersoll 259247e946e7SWyllys Ingersoll if (sig_len > *out_data_len) { 259347e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, sig); 259447e946e7SWyllys Ingersoll return (CKR_BUFFER_TOO_SMALL); 259547e946e7SWyllys Ingersoll } 259647e946e7SWyllys Ingersoll 259747e946e7SWyllys Ingersoll (void) memcpy(out_data, sig, sig_len); 259847e946e7SWyllys Ingersoll *out_data_len = sig_len; 259947e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, sig); 260047e946e7SWyllys Ingersoll 260147e946e7SWyllys Ingersoll return (CKR_OK); 260247e946e7SWyllys Ingersoll } 260347e946e7SWyllys Ingersoll 260447e946e7SWyllys Ingersoll CK_RV 260547e946e7SWyllys Ingersoll tpm_encrypt_data( 260647e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 260747e946e7SWyllys Ingersoll TSS_HKEY hKey, 260847e946e7SWyllys Ingersoll CK_BYTE *in_data, 260947e946e7SWyllys Ingersoll CK_ULONG in_data_len, 261047e946e7SWyllys Ingersoll CK_BYTE *out_data, 261147e946e7SWyllys Ingersoll CK_ULONG *out_data_len) 261247e946e7SWyllys Ingersoll { 261347e946e7SWyllys Ingersoll TSS_RESULT result; 261447e946e7SWyllys Ingersoll TSS_HENCDATA hEncData; 261547e946e7SWyllys Ingersoll BYTE *dataBlob, *modulus; 261647e946e7SWyllys Ingersoll UINT32 dataBlobSize, modLen; 261747e946e7SWyllys Ingersoll CK_ULONG chunklen, remain; 261847e946e7SWyllys Ingersoll CK_ULONG outlen; 2619*ab8176c2SWyllys Ingersoll UINT32 keyusage, scheme, maxsize; 262047e946e7SWyllys Ingersoll 262147e946e7SWyllys Ingersoll if ((result = Tspi_Context_CreateObject(hContext, 262247e946e7SWyllys Ingersoll TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_BIND, &hEncData))) { 262347e946e7SWyllys Ingersoll stlogit("Tspi_Context_CreateObject: 0x%0x - %s", 262447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 262547e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 262647e946e7SWyllys Ingersoll } 262747e946e7SWyllys Ingersoll /* 262847e946e7SWyllys Ingersoll * Figure out the modulus size so we can break the data 262947e946e7SWyllys Ingersoll * into smaller chunks if necessary. 263047e946e7SWyllys Ingersoll */ 263147e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 263247e946e7SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 263347e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 263447e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 263547e946e7SWyllys Ingersoll return (result); 263647e946e7SWyllys Ingersoll } 263747e946e7SWyllys Ingersoll /* we don't need the actual modulus */ 263847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 263947e946e7SWyllys Ingersoll 264047e946e7SWyllys Ingersoll /* 264147e946e7SWyllys Ingersoll * According to TSS spec for Tspi_Data_Bind (4.3.4.21.5), 2642*ab8176c2SWyllys Ingersoll * Max input data size varies depending on the key type and 2643*ab8176c2SWyllys Ingersoll * encryption scheme. 264447e946e7SWyllys Ingersoll */ 2645*ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, 2646*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_USAGE, &keyusage))) { 2647*ab8176c2SWyllys Ingersoll stlogit("Cannot find USAGE: %s\n", 2648*ab8176c2SWyllys Ingersoll Trspi_Error_String(result)); 2649*ab8176c2SWyllys Ingersoll return (result); 2650*ab8176c2SWyllys Ingersoll } 2651*ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO, 2652*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &scheme))) { 2653*ab8176c2SWyllys Ingersoll stlogit("Cannot find ENCSCHEME: %s\n", 2654*ab8176c2SWyllys Ingersoll Trspi_Error_String(result)); 2655*ab8176c2SWyllys Ingersoll return (result); 2656*ab8176c2SWyllys Ingersoll } 2657*ab8176c2SWyllys Ingersoll switch (scheme) { 2658*ab8176c2SWyllys Ingersoll case TSS_ES_RSAESPKCSV15: 2659*ab8176c2SWyllys Ingersoll if (keyusage == TSS_KEYUSAGE_BIND) 2660*ab8176c2SWyllys Ingersoll maxsize = 16; 2661*ab8176c2SWyllys Ingersoll else /* legacy */ 2662*ab8176c2SWyllys Ingersoll maxsize = 11; 2663*ab8176c2SWyllys Ingersoll break; 2664*ab8176c2SWyllys Ingersoll case TSS_ES_RSAESOAEP_SHA1_MGF1: 2665*ab8176c2SWyllys Ingersoll maxsize = 47; 2666*ab8176c2SWyllys Ingersoll break; 2667*ab8176c2SWyllys Ingersoll default: 2668*ab8176c2SWyllys Ingersoll maxsize = 0; 2669*ab8176c2SWyllys Ingersoll } 2670*ab8176c2SWyllys Ingersoll 2671*ab8176c2SWyllys Ingersoll modLen -= maxsize; 267247e946e7SWyllys Ingersoll 267347e946e7SWyllys Ingersoll chunklen = (in_data_len > modLen ? modLen : in_data_len); 267447e946e7SWyllys Ingersoll remain = in_data_len; 267547e946e7SWyllys Ingersoll outlen = 0; 267647e946e7SWyllys Ingersoll while (remain > 0) { 267747e946e7SWyllys Ingersoll if ((result = Tspi_Data_Bind(hEncData, hKey, 267847e946e7SWyllys Ingersoll chunklen, in_data))) { 267947e946e7SWyllys Ingersoll stlogit("Tspi_Data_Bind: 0x%0x - %s", 268047e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 268147e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 268247e946e7SWyllys Ingersoll } 268347e946e7SWyllys Ingersoll 268447e946e7SWyllys Ingersoll if ((result = Tspi_GetAttribData(hEncData, 268547e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATA_BLOB, 268647e946e7SWyllys Ingersoll TSS_TSPATTRIB_ENCDATABLOB_BLOB, 268747e946e7SWyllys Ingersoll &dataBlobSize, &dataBlob))) { 268847e946e7SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 268947e946e7SWyllys Ingersoll result, Trspi_Error_String(result)); 269047e946e7SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 269147e946e7SWyllys Ingersoll } 269247e946e7SWyllys Ingersoll 269347e946e7SWyllys Ingersoll if (outlen + dataBlobSize > *out_data_len) { 269447e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, dataBlob); 269547e946e7SWyllys Ingersoll return (CKR_DATA_LEN_RANGE); 269647e946e7SWyllys Ingersoll } 269747e946e7SWyllys Ingersoll 269847e946e7SWyllys Ingersoll (void) memcpy(out_data + outlen, 269947e946e7SWyllys Ingersoll dataBlob, dataBlobSize); 270047e946e7SWyllys Ingersoll 270147e946e7SWyllys Ingersoll outlen += dataBlobSize; 270247e946e7SWyllys Ingersoll in_data += chunklen; 270347e946e7SWyllys Ingersoll remain -= chunklen; 270447e946e7SWyllys Ingersoll 270547e946e7SWyllys Ingersoll if (chunklen > remain) 270647e946e7SWyllys Ingersoll chunklen = remain; 270747e946e7SWyllys Ingersoll 270847e946e7SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, dataBlob); 270947e946e7SWyllys Ingersoll } 271047e946e7SWyllys Ingersoll *out_data_len = outlen; 271147e946e7SWyllys Ingersoll 271247e946e7SWyllys Ingersoll return (CKR_OK); 271347e946e7SWyllys Ingersoll } 271447e946e7SWyllys Ingersoll 271547e946e7SWyllys Ingersoll CK_RV 271647e946e7SWyllys Ingersoll token_specific_rsa_encrypt( 271747e946e7SWyllys Ingersoll TSS_HCONTEXT hContext, 271847e946e7SWyllys Ingersoll CK_BYTE * in_data, 271947e946e7SWyllys Ingersoll CK_ULONG in_data_len, 272047e946e7SWyllys Ingersoll CK_BYTE * out_data, 272147e946e7SWyllys Ingersoll CK_ULONG * out_data_len, 272247e946e7SWyllys Ingersoll OBJECT * key_obj) 272347e946e7SWyllys Ingersoll { 272447e946e7SWyllys Ingersoll TSS_HKEY hKey; 272547e946e7SWyllys Ingersoll CK_RV rc; 272647e946e7SWyllys Ingersoll 272747e946e7SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 272847e946e7SWyllys Ingersoll return (rc); 272947e946e7SWyllys Ingersoll } 273047e946e7SWyllys Ingersoll 273147e946e7SWyllys Ingersoll rc = tpm_encrypt_data(hContext, hKey, in_data, in_data_len, 273247e946e7SWyllys Ingersoll out_data, out_data_len); 273347e946e7SWyllys Ingersoll 273447e946e7SWyllys Ingersoll return (rc); 273547e946e7SWyllys Ingersoll } 2736*ab8176c2SWyllys Ingersoll 2737*ab8176c2SWyllys Ingersoll /* 2738*ab8176c2SWyllys Ingersoll * RSA Verify Recover 2739*ab8176c2SWyllys Ingersoll * 2740*ab8176c2SWyllys Ingersoll * Public key crypto is done in software, not by the TPM. 2741*ab8176c2SWyllys Ingersoll * We bypass the TSPI library here in favor of calls directly 2742*ab8176c2SWyllys Ingersoll * to OpenSSL because we don't want to add any padding, the in_data (signature) 2743*ab8176c2SWyllys Ingersoll * already contains the data stream to be decrypted and is already 2744*ab8176c2SWyllys Ingersoll * padded and formatted correctly. 2745*ab8176c2SWyllys Ingersoll */ 2746*ab8176c2SWyllys Ingersoll CK_RV 2747*ab8176c2SWyllys Ingersoll token_specific_rsa_verify_recover( 2748*ab8176c2SWyllys Ingersoll TSS_HCONTEXT hContext, 2749*ab8176c2SWyllys Ingersoll CK_BYTE *in_data, /* signature */ 2750*ab8176c2SWyllys Ingersoll CK_ULONG in_data_len, 2751*ab8176c2SWyllys Ingersoll CK_BYTE *out_data, /* decrypted */ 2752*ab8176c2SWyllys Ingersoll CK_ULONG *out_data_len, 2753*ab8176c2SWyllys Ingersoll OBJECT *key_obj) 2754*ab8176c2SWyllys Ingersoll { 2755*ab8176c2SWyllys Ingersoll TSS_HKEY hKey; 2756*ab8176c2SWyllys Ingersoll TSS_RESULT result; 2757*ab8176c2SWyllys Ingersoll CK_RV rc; 2758*ab8176c2SWyllys Ingersoll BYTE *modulus; 2759*ab8176c2SWyllys Ingersoll UINT32 modLen; 2760*ab8176c2SWyllys Ingersoll RSA *rsa = NULL; 2761*ab8176c2SWyllys Ingersoll uchar_t exp[] = { 0x01, 0x00, 0x01 }; 2762*ab8176c2SWyllys Ingersoll int sslrv, num; 2763*ab8176c2SWyllys Ingersoll BYTE temp[MAX_RSA_KEYLENGTH]; 2764*ab8176c2SWyllys Ingersoll int i; 2765*ab8176c2SWyllys Ingersoll 2766*ab8176c2SWyllys Ingersoll if ((rc = token_rsa_load_key(hContext, key_obj, &hKey))) { 2767*ab8176c2SWyllys Ingersoll return (rc); 2768*ab8176c2SWyllys Ingersoll } 2769*ab8176c2SWyllys Ingersoll 2770*ab8176c2SWyllys Ingersoll if ((result = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_RSAKEY_INFO, 2771*ab8176c2SWyllys Ingersoll TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &modLen, &modulus))) { 2772*ab8176c2SWyllys Ingersoll stlogit("Tspi_GetAttribData: 0x%0x - %s", 2773*ab8176c2SWyllys Ingersoll result, Trspi_Error_String(result)); 2774*ab8176c2SWyllys Ingersoll return (CKR_FUNCTION_FAILED); 2775*ab8176c2SWyllys Ingersoll } 2776*ab8176c2SWyllys Ingersoll 2777*ab8176c2SWyllys Ingersoll if (in_data_len != modLen) { 2778*ab8176c2SWyllys Ingersoll rc = CKR_SIGNATURE_LEN_RANGE; 2779*ab8176c2SWyllys Ingersoll goto end; 2780*ab8176c2SWyllys Ingersoll } 2781*ab8176c2SWyllys Ingersoll 2782*ab8176c2SWyllys Ingersoll rsa = RSA_new(); 2783*ab8176c2SWyllys Ingersoll if (rsa == NULL) { 2784*ab8176c2SWyllys Ingersoll rc = CKR_HOST_MEMORY; 2785*ab8176c2SWyllys Ingersoll goto end; 2786*ab8176c2SWyllys Ingersoll } 2787*ab8176c2SWyllys Ingersoll 2788*ab8176c2SWyllys Ingersoll rsa->n = BN_bin2bn(modulus, modLen, rsa->n); 2789*ab8176c2SWyllys Ingersoll rsa->e = BN_bin2bn(exp, sizeof (exp), rsa->e); 2790*ab8176c2SWyllys Ingersoll if (rsa->n == NULL || rsa->e == NULL) { 2791*ab8176c2SWyllys Ingersoll rc = CKR_HOST_MEMORY; 2792*ab8176c2SWyllys Ingersoll goto end; 2793*ab8176c2SWyllys Ingersoll } 2794*ab8176c2SWyllys Ingersoll 2795*ab8176c2SWyllys Ingersoll /* use RSA_NO_PADDING because the data is already padded (PKCS1) */ 2796*ab8176c2SWyllys Ingersoll sslrv = RSA_public_encrypt(in_data_len, in_data, out_data, 2797*ab8176c2SWyllys Ingersoll rsa, RSA_NO_PADDING); 2798*ab8176c2SWyllys Ingersoll if (sslrv == -1) { 2799*ab8176c2SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 2800*ab8176c2SWyllys Ingersoll goto end; 2801*ab8176c2SWyllys Ingersoll } 2802*ab8176c2SWyllys Ingersoll 2803*ab8176c2SWyllys Ingersoll /* Strip leading 0's before stripping the padding */ 2804*ab8176c2SWyllys Ingersoll for (i = 0; i < sslrv; i++) 2805*ab8176c2SWyllys Ingersoll if (out_data[i] != 0) 2806*ab8176c2SWyllys Ingersoll break; 2807*ab8176c2SWyllys Ingersoll 2808*ab8176c2SWyllys Ingersoll num = BN_num_bytes(rsa->n); 2809*ab8176c2SWyllys Ingersoll 2810*ab8176c2SWyllys Ingersoll /* Use OpenSSL function for stripping PKCS#1 padding */ 2811*ab8176c2SWyllys Ingersoll sslrv = RSA_padding_check_PKCS1_type_1(temp, sizeof (temp), 2812*ab8176c2SWyllys Ingersoll &out_data[i], sslrv - i, num); 2813*ab8176c2SWyllys Ingersoll 2814*ab8176c2SWyllys Ingersoll if (sslrv < 0) { 2815*ab8176c2SWyllys Ingersoll rc = CKR_FUNCTION_FAILED; 2816*ab8176c2SWyllys Ingersoll goto end; 2817*ab8176c2SWyllys Ingersoll } 2818*ab8176c2SWyllys Ingersoll 2819*ab8176c2SWyllys Ingersoll if (*out_data_len < sslrv) { 2820*ab8176c2SWyllys Ingersoll rc = CKR_BUFFER_TOO_SMALL; 2821*ab8176c2SWyllys Ingersoll *out_data_len = 0; 2822*ab8176c2SWyllys Ingersoll goto end; 2823*ab8176c2SWyllys Ingersoll } 2824*ab8176c2SWyllys Ingersoll 2825*ab8176c2SWyllys Ingersoll /* The return code indicates the number of bytes remaining */ 2826*ab8176c2SWyllys Ingersoll (void) memcpy(out_data, temp, sslrv); 2827*ab8176c2SWyllys Ingersoll *out_data_len = sslrv; 2828*ab8176c2SWyllys Ingersoll end: 2829*ab8176c2SWyllys Ingersoll Tspi_Context_FreeMemory(hContext, modulus); 2830*ab8176c2SWyllys Ingersoll if (rsa) 2831*ab8176c2SWyllys Ingersoll RSA_free(rsa); 2832*ab8176c2SWyllys Ingersoll 2833*ab8176c2SWyllys Ingersoll return (rc); 2834*ab8176c2SWyllys Ingersoll } 2835