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