#include "tpmtok_int.h"
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
#define ALTERNATE_KEYSTORE_PATH "PKCS11_TPM_DIR"
#define PWD_BUFFER_SIZE 1024
static char keystore_path[MAXPATHLEN];
static boolean_t keystore_path_initialized = 0;
extern TSS_HKEY hPrivateLeafKey;
static CK_RV
restore_private_token_object(TSS_HCONTEXT, CK_BYTE *, CK_ULONG, OBJECT *);
static struct flock fl = {
0,
0,
0,
0,
0,
0,
{0, 0, 0, 0}
};
static int
lockfile(int fd, int op)
{
fl.l_type = op;
return (fcntl(fd, F_SETLKW, &fl));
}
static char *
get_user_default_path(char *home_path)
{
struct passwd pwd, *user_info;
char pwdbuf[PWD_BUFFER_SIZE];
if (getpwuid_r(getuid(), &pwd, pwdbuf, PWD_BUFFER_SIZE,
&user_info) != 0)
return (NULL);
(void) snprintf(home_path, MAXPATHLEN, "/var/tpm/pkcs11/%s",
user_info ? user_info->pw_name : "");
return (home_path);
}
char *
get_tpm_keystore_path()
{
char *env_val;
char home_path[MAXPATHLEN];
if (!keystore_path_initialized) {
env_val = getenv(ALTERNATE_KEYSTORE_PATH);
bzero(keystore_path, sizeof (keystore_path));
if ((env_val == NULL) || (strcmp(env_val, "") == 0)) {
char *p = get_user_default_path(home_path);
if (p == NULL)
return (NULL);
(void) snprintf(keystore_path, MAXPATHLEN, "%s", p);
} else {
(void) snprintf(keystore_path, MAXPATHLEN, "%s",
env_val);
}
keystore_path_initialized = 1;
}
return (keystore_path);
}
static CK_RV
create_keystore_dir()
{
char *ksdir = get_tpm_keystore_path();
char objdir[MAXPATHLEN];
CK_RV rv = 0;
if (ksdir == NULL)
return (CKR_FUNCTION_FAILED);
if (mkdir(ksdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
if (errno == EEXIST) {
rv = 0;
} else {
return (CKR_FUNCTION_FAILED);
}
}
if (rv == 0) {
(void) snprintf(objdir, sizeof (objdir),
"%s/%s", ksdir, TOKEN_OBJ_DIR);
if (mkdir(objdir, S_IRUSR|S_IWUSR|S_IXUSR) < 0) {
if (errno == EEXIST) {
rv = 0;
} else {
return (CKR_FUNCTION_FAILED);
}
}
}
return (CKR_OK);
}
static void
set_perm(int file)
{
(void) fchmod(file, S_IRUSR|S_IWUSR);
}
#define READ_TOKEN_INFO_STR(fp, rec, reclen) rc = fread(rec, reclen, 1, fp); \
if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; }
#define READ_TOKEN_INFO_UINT32(fp, rec) rc = fread(&fieldval, \
sizeof (UINT32), 1, fp); \
if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto out_unlock; } \
rec = (CK_ULONG)fieldval;
CK_RV
load_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td)
{
FILE *fp;
CK_BYTE fname[MAXPATHLEN];
CK_RV rc;
UINT32 fieldval;
char *p = get_tpm_keystore_path();
if (p == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s", p, TOKEN_DATA_FILE);
rc = XProcLock(xproclock);
if (rc != CKR_OK)
return (rc);
fp = fopen((char *)fname, "r");
if (!fp) {
if (errno == ENOENT) {
(void) XProcUnLock(xproclock);
rc = create_keystore_dir();
if (rc != 0)
goto out_nolock;
rc = init_token_data(hContext, td);
if (rc != CKR_OK) {
goto out_nolock;
}
rc = XProcLock(xproclock);
if (rc != CKR_OK) {
goto out_nolock;
}
fp = fopen((char *)fname, "r");
if (!fp) {
LogError("failed opening %s for read: %s",
fname, (char *)strerror(errno));
rc = CKR_FUNCTION_FAILED;
goto out_unlock;
}
} else {
rc = CKR_FUNCTION_FAILED;
goto out_unlock;
}
}
if (lockfile(fileno(fp), F_RDLCK)) {
(void) fclose(fp);
rc = CKR_FUNCTION_FAILED;
goto out_unlock;
}
set_perm(fileno(fp));
READ_TOKEN_INFO_STR(fp, td->token_info.label,
sizeof (td->token_info.label));
READ_TOKEN_INFO_STR(fp, td->token_info.manufacturerID,
sizeof (td->token_info.manufacturerID));
READ_TOKEN_INFO_STR(fp, td->token_info.model,
sizeof (td->token_info.model));
READ_TOKEN_INFO_STR(fp, td->token_info.serialNumber,
sizeof (td->token_info.serialNumber));
READ_TOKEN_INFO_UINT32(fp, td->token_info.flags);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory);
READ_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory);
READ_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion,
sizeof (td->token_info.hardwareVersion));
READ_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion,
sizeof (td->token_info.firmwareVersion));
READ_TOKEN_INFO_STR(fp, td->token_info.utcTime,
sizeof (td->token_info.utcTime));
READ_TOKEN_INFO_STR(fp, td->user_pin_sha,
sizeof (td->user_pin_sha));
READ_TOKEN_INFO_STR(fp, td->so_pin_sha,
sizeof (td->so_pin_sha));
READ_TOKEN_INFO_STR(fp, td->next_token_object_name,
sizeof (td->next_token_object_name));
READ_TOKEN_INFO_STR(fp, &td->tweak_vector,
sizeof (td->tweak_vector));
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
if (rc == 0)
rc = CKR_FUNCTION_FAILED;
else
rc = CKR_OK;
out_unlock:
(void) XProcUnLock(xproclock);
out_nolock:
return (rc);
}
#define WRITE_TOKEN_INFO_STR(fp, rec, reclen) rc = fwrite(rec, reclen, 1, fp); \
if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; }
#define WRITE_TOKEN_INFO_UINT32(fp, rec) fieldval = (UINT32)rec; \
rc = fwrite(&fieldval, sizeof (UINT32), 1, fp); \
if (rc != 1) { rc = CKR_FUNCTION_FAILED; goto done; }
CK_RV
save_token_data(TOKEN_DATA *td)
{
FILE *fp;
CK_RV rc;
CK_BYTE fname[MAXPATHLEN];
char *p = get_tpm_keystore_path();
UINT32 fieldval;
if (p == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s", p, TOKEN_DATA_FILE);
rc = XProcLock(xproclock);
if (rc != CKR_OK)
goto out_nolock;
fp = fopen((char *)fname, "w");
if (!fp) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
if (lockfile(fileno(fp), F_WRLCK)) {
rc = CKR_FUNCTION_FAILED;
(void) fclose(fp);
goto done;
}
set_perm(fileno(fp));
WRITE_TOKEN_INFO_STR(fp, td->token_info.label,
sizeof (td->token_info.label));
WRITE_TOKEN_INFO_STR(fp, td->token_info.manufacturerID,
sizeof (td->token_info.manufacturerID));
WRITE_TOKEN_INFO_STR(fp, td->token_info.model,
sizeof (td->token_info.model));
WRITE_TOKEN_INFO_STR(fp, td->token_info.serialNumber,
sizeof (td->token_info.serialNumber));
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.flags);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxSessionCount);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulSessionCount);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulRwSessionCount);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMaxPinLen);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulMinPinLen);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPublicMemory);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePublicMemory);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulTotalPrivateMemory);
WRITE_TOKEN_INFO_UINT32(fp, td->token_info.ulFreePrivateMemory);
WRITE_TOKEN_INFO_STR(fp, &td->token_info.hardwareVersion,
sizeof (td->token_info.hardwareVersion));
WRITE_TOKEN_INFO_STR(fp, &td->token_info.firmwareVersion,
sizeof (td->token_info.firmwareVersion));
WRITE_TOKEN_INFO_STR(fp, td->token_info.utcTime,
sizeof (td->token_info.utcTime));
WRITE_TOKEN_INFO_STR(fp, td->user_pin_sha,
sizeof (td->user_pin_sha));
WRITE_TOKEN_INFO_STR(fp, td->so_pin_sha,
sizeof (td->so_pin_sha));
WRITE_TOKEN_INFO_STR(fp, td->next_token_object_name,
sizeof (td->next_token_object_name));
WRITE_TOKEN_INFO_STR(fp, &td->tweak_vector,
sizeof (td->tweak_vector));
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
rc = CKR_OK;
done:
(void) XProcUnLock(xproclock);
out_nolock:
return (rc);
}
CK_RV
save_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
{
FILE *fp = NULL;
CK_BYTE line[100];
CK_RV rc;
CK_BYTE fname[MAXPATHLEN];
char *p = get_tpm_keystore_path();
if (p == NULL)
return (CKR_FUNCTION_FAILED);
if (object_is_private(obj) == TRUE)
rc = save_private_token_object(hContext, obj);
else
rc = save_public_token_object(obj);
if (rc != CKR_OK)
return (rc);
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/%s", p, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
fp = fopen((char *)fname, "r");
if (fp) {
if (lockfile(fileno(fp), F_RDLCK)) {
(void) fclose(fp);
return (CKR_FUNCTION_FAILED);
}
set_perm(fileno(fp));
while (!feof(fp)) {
(void) fgets((char *)line, 50, fp);
if (!feof(fp)) {
line[strlen((char *)line) - 1] = 0;
if (strcmp((char *)line,
(char *)(obj->name)) == 0) {
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
return (CKR_OK);
}
}
}
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
}
fp = fopen((char *)fname, "a");
if (!fp)
return (CKR_FUNCTION_FAILED);
if (lockfile(fileno(fp), F_WRLCK)) {
(void) fclose(fp);
return (CKR_FUNCTION_FAILED);
}
set_perm(fileno(fp));
(void) fprintf(fp, "%s\n", obj->name);
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
return (CKR_OK);
}
CK_RV
save_public_token_object(OBJECT *obj)
{
FILE *fp = NULL;
CK_BYTE *cleartxt = NULL;
CK_BYTE fname[MAXPATHLEN];
UINT32 cleartxt_len;
CK_BBOOL flag = FALSE;
CK_RV rc;
UINT32 total_len;
char *p = get_tpm_keystore_path();
if (p == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
rc = object_flatten(obj, &cleartxt, &cleartxt_len);
if (rc != CKR_OK)
goto error;
fp = fopen((char *)fname, "w");
if (!fp) {
LogError("Error opening %s - %s", fname,
(char *)strerror(errno));
rc = CKR_FUNCTION_FAILED;
goto error;
}
if (lockfile(fileno(fp), F_WRLCK)) {
(void) fclose(fp);
return (CKR_FUNCTION_FAILED);
}
set_perm(fileno(fp));
total_len = cleartxt_len + sizeof (UINT32) + sizeof (CK_BBOOL);
(void) fwrite(&total_len, sizeof (total_len), 1, fp);
(void) fwrite(&flag, sizeof (flag), 1, fp);
(void) fwrite(cleartxt, cleartxt_len, 1, fp);
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
free(cleartxt);
return (CKR_OK);
error:
if (fp)
(void) fclose(fp);
if (cleartxt)
free(cleartxt);
return (rc);
}
CK_RV
save_private_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
{
FILE *fp = NULL;
CK_BYTE *obj_data = NULL;
CK_BYTE *cleartxt = NULL;
CK_BYTE *ciphertxt = NULL;
CK_BYTE *ptr = NULL;
CK_BYTE fname[100];
CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
CK_BBOOL flag;
CK_RV rc;
CK_ULONG ciphertxt_len;
UINT32 cleartxt_len;
UINT32 padded_len;
UINT32 obj_data_len_32;
UINT32 total_len;
UINT32 chunksize, blocks;
char *p = get_tpm_keystore_path();
if (p == NULL)
return (CKR_FUNCTION_FAILED);
rc = object_flatten(obj, &obj_data, &obj_data_len_32);
if (rc != CKR_OK) {
goto error;
}
if ((rc = compute_sha(obj_data, obj_data_len_32, hash_sha)) != CKR_OK)
goto error;
chunksize = RSA_BLOCK_SIZE - (2 * SHA1_DIGEST_LENGTH + 2) - 5;
cleartxt_len = sizeof (UINT32) + obj_data_len_32 + SHA1_DIGEST_LENGTH;
blocks = cleartxt_len / chunksize + ((cleartxt_len % chunksize) > 0);
padded_len = RSA_BLOCK_SIZE * blocks;
cleartxt = (CK_BYTE *)malloc(padded_len);
ciphertxt = (CK_BYTE *)malloc(padded_len);
if (!cleartxt || !ciphertxt) {
rc = CKR_HOST_MEMORY;
goto error;
}
ciphertxt_len = padded_len;
ptr = cleartxt;
(void) memcpy(ptr, &obj_data_len_32, sizeof (UINT32));
ptr += sizeof (UINT32);
(void) memcpy(ptr, obj_data, obj_data_len_32);
ptr += obj_data_len_32;
(void) memcpy(ptr, hash_sha, SHA1_DIGEST_LENGTH);
(void) add_pkcs_padding(cleartxt + cleartxt_len, RSA_BLOCK_SIZE,
cleartxt_len, padded_len);
rc = tpm_encrypt_data(hContext, hPrivateLeafKey, cleartxt, cleartxt_len,
ciphertxt, &ciphertxt_len);
if (rc != CKR_OK) {
goto error;
}
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/%s", p, TOKEN_OBJ_DIR, obj->name);
fp = fopen((char *)fname, "w");
if (!fp) {
rc = CKR_FUNCTION_FAILED;
goto error;
}
if (lockfile(fileno(fp), F_WRLCK)) {
rc = CKR_FUNCTION_FAILED;
goto error;
}
set_perm(fileno(fp));
total_len = sizeof (UINT32) + sizeof (CK_BBOOL) + (UINT32)ciphertxt_len;
flag = TRUE;
(void) fwrite(&total_len, sizeof (UINT32), 1, fp);
(void) fwrite(&flag, sizeof (CK_BBOOL), 1, fp);
(void) fwrite(ciphertxt, ciphertxt_len, 1, fp);
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
free(obj_data);
free(cleartxt);
free(ciphertxt);
return (CKR_OK);
error:
if (fp)
(void) fclose(fp);
if (obj_data)
free(obj_data);
if (cleartxt)
free(cleartxt);
if (ciphertxt)
free(ciphertxt);
return (rc);
}
CK_RV
load_public_token_objects(void)
{
FILE *fp1 = NULL, *fp2 = NULL;
CK_BYTE *buf = NULL;
CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
CK_BBOOL priv;
UINT32 size;
char *ksdir = get_tpm_keystore_path();
if (ksdir == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf((char *)iname, sizeof (iname),
"%s/%s/%s", ksdir,
TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
fp1 = fopen((char *)iname, "r");
if (!fp1)
return (CKR_OK);
if (lockfile(fileno(fp1), F_RDLCK)) {
(void) fclose(fp1);
return (CKR_FUNCTION_FAILED);
}
while (!feof(fp1)) {
(void) fgets((char *)tmp, 50, fp1);
if (feof(fp1))
break;
tmp[strlen((char *)tmp) - 1] = 0;
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/", ksdir, TOKEN_OBJ_DIR);
(void) strncat((char *)fname, (const char *)tmp,
(size_t)sizeof (fname));
fp2 = fopen((char *)fname, "r");
if (!fp2)
continue;
(void) fread(&size, sizeof (UINT32), 1, fp2);
(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
if (priv == TRUE) {
(void) fclose(fp2);
continue;
}
size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
buf = (CK_BYTE *)malloc(size);
if (!buf) {
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
return (CKR_HOST_MEMORY);
}
(void) fread(buf, size, 1, fp2);
if (pthread_mutex_lock(&obj_list_mutex)) {
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
free(buf);
return (CKR_FUNCTION_FAILED);
}
(void) object_mgr_restore_obj(buf, NULL);
(void) pthread_mutex_unlock(&obj_list_mutex);
free(buf);
(void) fclose(fp2);
}
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
return (CKR_OK);
}
CK_RV
load_private_token_objects(TSS_HCONTEXT hContext)
{
FILE *fp1 = NULL, *fp2 = NULL;
CK_BYTE *buf = NULL;
CK_BYTE tmp[MAXPATHLEN], fname[MAXPATHLEN], iname[MAXPATHLEN];
CK_BBOOL priv;
UINT32 size;
CK_RV rc;
char *ksdir = get_tpm_keystore_path();
if (ksdir == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf((char *)iname, sizeof (iname),
"%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
fp1 = fopen((char *)iname, "r");
if (!fp1)
return (CKR_OK);
if (lockfile(fileno(fp1), F_RDLCK)) {
rc = CKR_FUNCTION_FAILED;
goto error;
}
while (!feof(fp1)) {
(void) fgets((char *)tmp, sizeof (tmp), fp1);
if (feof(fp1))
break;
tmp[strlen((char *)tmp) - 1] = 0;
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/%s", ksdir, TOKEN_OBJ_DIR, tmp);
fp2 = fopen((char *)fname, "r");
if (!fp2)
continue;
(void) fread(&size, sizeof (UINT32), 1, fp2);
(void) fread(&priv, sizeof (CK_BBOOL), 1, fp2);
if (priv == FALSE) {
(void) fclose(fp2);
continue;
}
size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
buf = (CK_BYTE *)malloc(size);
if (!buf) {
rc = CKR_HOST_MEMORY;
goto error;
}
rc = fread((char *)buf, size, 1, fp2);
if (rc != 1) {
rc = CKR_FUNCTION_FAILED;
goto error;
}
if (pthread_mutex_lock(&obj_list_mutex)) {
rc = CKR_FUNCTION_FAILED;
goto error;
}
rc = restore_private_token_object(hContext, buf, size, NULL);
(void) pthread_mutex_unlock(&obj_list_mutex);
if (rc != CKR_OK)
goto error;
free(buf);
(void) fclose(fp2);
}
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
return (CKR_OK);
error:
if (buf)
free(buf);
if (fp1) {
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
}
if (fp2)
(void) fclose(fp2);
return (rc);
}
static CK_RV
restore_private_token_object(
TSS_HCONTEXT hContext,
CK_BYTE *data,
CK_ULONG len,
OBJECT *pObj)
{
CK_BYTE * cleartxt = NULL;
CK_BYTE * obj_data = NULL;
CK_BYTE *ptr = NULL;
CK_BYTE hash_sha[SHA1_DIGEST_LENGTH];
UINT32 cleartxt_len;
UINT32 obj_data_len;
CK_RV rc;
cleartxt_len = len;
cleartxt = (CK_BYTE *)malloc(len);
if (!cleartxt) {
rc = CKR_HOST_MEMORY;
goto done;
}
rc = tpm_decrypt_data(hContext, hPrivateLeafKey, data, len,
cleartxt, &len);
if (rc != CKR_OK) {
goto done;
}
(void) strip_pkcs_padding(cleartxt, len, &cleartxt_len);
if (cleartxt_len > len) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
ptr = cleartxt;
bcopy(ptr, &obj_data_len, sizeof (UINT32));
ptr += sizeof (UINT32);
obj_data = ptr;
if ((rc = compute_sha(ptr, obj_data_len, hash_sha)) != CKR_OK)
goto done;
ptr += obj_data_len;
if (memcmp((const void *)ptr, (const void *)hash_sha,
(size_t)SHA1_DIGEST_LENGTH) != 0) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
(void) object_mgr_restore_obj(obj_data, pObj);
rc = CKR_OK;
done:
if (cleartxt)
free(cleartxt);
return (rc);
}
CK_RV
reload_token_object(TSS_HCONTEXT hContext, OBJECT *obj)
{
FILE *fp = NULL;
CK_BYTE *buf = NULL;
CK_BYTE fname[MAXPATHLEN];
CK_BBOOL priv;
UINT32 size;
CK_RV rc;
char *p = get_tpm_keystore_path();
if (p == NULL)
return (CKR_FUNCTION_FAILED);
(void) memset((char *)fname, 0x0, sizeof (fname));
(void) snprintf((char *)fname, sizeof (fname),
"%s/%s/", p, TOKEN_OBJ_DIR);
(void) strncat((char *)fname, (char *)obj->name, sizeof (fname));
fp = fopen((char *)fname, "r");
if (!fp) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
if (lockfile(fileno(fp), F_RDLCK)) {
rc = CKR_FUNCTION_FAILED;
goto done;
}
set_perm(fileno(fp));
(void) fread(&size, sizeof (UINT32), 1, fp);
(void) fread(&priv, sizeof (CK_BBOOL), 1, fp);
size = size - sizeof (UINT32) - sizeof (CK_BBOOL);
buf = (CK_BYTE *)malloc(size);
if (!buf) {
rc = CKR_HOST_MEMORY;
goto done;
}
(void) fread(buf, size, 1, fp);
if (priv) {
rc = restore_private_token_object(hContext, buf, size, obj);
} else {
rc = object_mgr_restore_obj(buf, obj);
}
done:
if (fp) {
(void) lockfile(fileno(fp), F_UNLCK);
(void) fclose(fp);
}
if (buf)
free(buf);
return (rc);
}
static int
islink(char *fname)
{
struct stat st;
if (stat((const char *)fname, &st))
return (-1);
else if (S_ISLNK(st.st_mode))
return (1);
return (0);
}
CK_RV
delete_token_object(OBJECT *obj)
{
FILE *fp1, *fp2;
CK_BYTE line[100];
char objidx[MAXPATHLEN], idxtmp[MAXPATHLEN], fname[MAXPATHLEN];
char *ksdir = get_tpm_keystore_path();
if (ksdir == NULL)
return (CKR_FUNCTION_FAILED);
(void) snprintf(objidx, sizeof (objidx),
"%s/%s/%s", ksdir, TOKEN_OBJ_DIR, TOKEN_OBJ_INDEX_FILE);
(void) snprintf(idxtmp, sizeof (idxtmp),
"%s/IDX.TMP", ksdir, TOKEN_OBJ_DIR);
if (islink(objidx) != 0)
return (CKR_FUNCTION_FAILED);
if (islink(idxtmp) == 1)
return (CKR_FUNCTION_FAILED);
fp1 = fopen(objidx, "r");
fp2 = fopen(idxtmp, "w");
if (!fp1 || !fp2) {
if (fp1)
(void) fclose(fp1);
if (fp2)
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
if (lockfile(fileno(fp1), F_RDLCK)) {
(void) fclose(fp1);
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
if (lockfile(fileno(fp2), F_WRLCK)) {
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
set_perm(fileno(fp2));
while (!feof(fp1)) {
(void) fgets((char *)line, 50, fp1);
if (!feof(fp1)) {
line[ strlen((char *)line)-1 ] = 0;
if (strcmp((char *)line, (char *)obj->name))
(void) fprintf(fp2, "%s\n", line);
}
}
(void) lockfile(fileno(fp1), F_UNLCK);
(void) lockfile(fileno(fp2), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
fp2 = fopen(objidx, "w");
fp1 = fopen(idxtmp, "r");
if (!fp1 || !fp2) {
if (fp1)
(void) fclose(fp1);
if (fp2)
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
if (lockfile(fileno(fp1), F_RDLCK)) {
(void) fclose(fp1);
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
if (lockfile(fileno(fp2), F_WRLCK)) {
(void) lockfile(fileno(fp1), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
return (CKR_FUNCTION_FAILED);
}
set_perm(fileno(fp2));
while (!feof(fp1)) {
(void) fgets((char *)line, 50, fp1);
if (!feof(fp1))
(void) fprintf(fp2, "%s", (char *)line);
}
(void) lockfile(fileno(fp1), F_UNLCK);
(void) lockfile(fileno(fp2), F_UNLCK);
(void) fclose(fp1);
(void) fclose(fp2);
(void) snprintf(fname, sizeof (fname),
"%s/%s/%s", ksdir, TOKEN_OBJ_DIR, (char *)obj->name);
(void) unlink(fname);
return (CKR_OK);
}