147e946e7SWyllys Ingersoll /*
247e946e7SWyllys Ingersoll  * The Initial Developer of the Original Code is International
347e946e7SWyllys Ingersoll  * Business Machines Corporation. Portions created by IBM
447e946e7SWyllys Ingersoll  * Corporation are Copyright (C) 2005 International Business
547e946e7SWyllys Ingersoll  * Machines Corporation. All Rights Reserved.
647e946e7SWyllys Ingersoll  *
747e946e7SWyllys Ingersoll  * This program is free software; you can redistribute it and/or modify
847e946e7SWyllys Ingersoll  * it under the terms of the Common Public License as published by
947e946e7SWyllys Ingersoll  * IBM Corporation; either version 1 of the License, or (at your option)
1047e946e7SWyllys Ingersoll  * any later version.
1147e946e7SWyllys Ingersoll  *
1247e946e7SWyllys Ingersoll  * This program is distributed in the hope that it will be useful,
1347e946e7SWyllys Ingersoll  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1447e946e7SWyllys Ingersoll  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1547e946e7SWyllys Ingersoll  * Common Public License for more details.
1647e946e7SWyllys Ingersoll  *
1747e946e7SWyllys Ingersoll  * You should have received a copy of the Common Public License
1847e946e7SWyllys Ingersoll  * along with this program; if not, a copy can be viewed at
1947e946e7SWyllys Ingersoll  * http://www.opensource.org/licenses/cpl1.0.php.
2047e946e7SWyllys Ingersoll  */
2147e946e7SWyllys Ingersoll 
2247e946e7SWyllys Ingersoll /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
2347e946e7SWyllys Ingersoll /*
2447e946e7SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2547e946e7SWyllys Ingersoll  * Use is subject to license terms.
2647e946e7SWyllys Ingersoll  */
2747e946e7SWyllys Ingersoll 
2847e946e7SWyllys Ingersoll #include "tpmtok_int.h"
2947e946e7SWyllys Ingersoll 
3047e946e7SWyllys Ingersoll static CK_SLOT_INFO    slot_info;
3147e946e7SWyllys Ingersoll 
3247e946e7SWyllys Ingersoll // Function:  dlist_add_as_first()
3347e946e7SWyllys Ingersoll //
3447e946e7SWyllys Ingersoll // Adds the specified node to the start of the list
3547e946e7SWyllys Ingersoll //
3647e946e7SWyllys Ingersoll // Returns:  pointer to the start of the list
3747e946e7SWyllys Ingersoll //
3847e946e7SWyllys Ingersoll DL_NODE *
dlist_add_as_first(DL_NODE * list,void * data)3947e946e7SWyllys Ingersoll dlist_add_as_first(DL_NODE *list, void *data)
4047e946e7SWyllys Ingersoll {
4147e946e7SWyllys Ingersoll 	DL_NODE *node = NULL;
4247e946e7SWyllys Ingersoll 
4347e946e7SWyllys Ingersoll 	if (! data)
4447e946e7SWyllys Ingersoll 		return (list);
4547e946e7SWyllys Ingersoll 	node = (DL_NODE *)malloc(sizeof (DL_NODE));
4647e946e7SWyllys Ingersoll 	if (! node)
4747e946e7SWyllys Ingersoll 		return (NULL);
4847e946e7SWyllys Ingersoll 	node->data = data;
4947e946e7SWyllys Ingersoll 	node->prev = NULL;
5047e946e7SWyllys Ingersoll 	node->next = list;
5147e946e7SWyllys Ingersoll 	if (list)
5247e946e7SWyllys Ingersoll 		list->prev = node;
5347e946e7SWyllys Ingersoll 
5447e946e7SWyllys Ingersoll 	return (node);
5547e946e7SWyllys Ingersoll }
5647e946e7SWyllys Ingersoll 
5747e946e7SWyllys Ingersoll 
5847e946e7SWyllys Ingersoll // Function:  dlist_add_as_last()
5947e946e7SWyllys Ingersoll //
6047e946e7SWyllys Ingersoll // Adds the specified node to the end of the list
6147e946e7SWyllys Ingersoll //
6247e946e7SWyllys Ingersoll // Returns:  pointer to the start of the list
6347e946e7SWyllys Ingersoll //
6447e946e7SWyllys Ingersoll DL_NODE *
dlist_add_as_last(DL_NODE * list,void * data)6547e946e7SWyllys Ingersoll dlist_add_as_last(DL_NODE *list, void *data) {
6647e946e7SWyllys Ingersoll 	DL_NODE *node = NULL;
6747e946e7SWyllys Ingersoll 
6847e946e7SWyllys Ingersoll 	if (! data)
6947e946e7SWyllys Ingersoll 		return (list);
7047e946e7SWyllys Ingersoll 	node = (DL_NODE *)malloc(sizeof (DL_NODE));
7147e946e7SWyllys Ingersoll 	if (! node)
7247e946e7SWyllys Ingersoll 		return (NULL);
7347e946e7SWyllys Ingersoll 	node->data = data;
7447e946e7SWyllys Ingersoll 	node->next = NULL;
7547e946e7SWyllys Ingersoll 
7647e946e7SWyllys Ingersoll 	if (! list) {
7747e946e7SWyllys Ingersoll 		node->prev = NULL;
7847e946e7SWyllys Ingersoll 		return (node);
7947e946e7SWyllys Ingersoll 	} else {
8047e946e7SWyllys Ingersoll 		DL_NODE *temp = dlist_get_last(list);
8147e946e7SWyllys Ingersoll 		temp->next = node;
8247e946e7SWyllys Ingersoll 		node->prev = temp;
8347e946e7SWyllys Ingersoll 
8447e946e7SWyllys Ingersoll 		return (list);
8547e946e7SWyllys Ingersoll 	}
8647e946e7SWyllys Ingersoll }
8747e946e7SWyllys Ingersoll 
8847e946e7SWyllys Ingersoll 
8947e946e7SWyllys Ingersoll // Function:  dlist_find()
9047e946e7SWyllys Ingersoll //
9147e946e7SWyllys Ingersoll DL_NODE *
dlist_find(DL_NODE * list,void * data)9247e946e7SWyllys Ingersoll dlist_find(DL_NODE *list, void *data)
9347e946e7SWyllys Ingersoll {
9447e946e7SWyllys Ingersoll 	DL_NODE *node = list;
9547e946e7SWyllys Ingersoll 
9647e946e7SWyllys Ingersoll 	while (node && node->data != data)
9747e946e7SWyllys Ingersoll 	node = node->next;
9847e946e7SWyllys Ingersoll 
9947e946e7SWyllys Ingersoll 	return (node);
10047e946e7SWyllys Ingersoll }
10147e946e7SWyllys Ingersoll 
10247e946e7SWyllys Ingersoll 
10347e946e7SWyllys Ingersoll // Function:  dlist_get_first()
10447e946e7SWyllys Ingersoll //
10547e946e7SWyllys Ingersoll // Returns the last node in the list or NULL if list is empty
10647e946e7SWyllys Ingersoll //
10747e946e7SWyllys Ingersoll DL_NODE *
dlist_get_first(DL_NODE * list)10847e946e7SWyllys Ingersoll dlist_get_first(DL_NODE *list) {
10947e946e7SWyllys Ingersoll 	DL_NODE *temp = list;
11047e946e7SWyllys Ingersoll 
11147e946e7SWyllys Ingersoll 	if (! list)
11247e946e7SWyllys Ingersoll 		return (NULL);
11347e946e7SWyllys Ingersoll 	while (temp->prev != NULL)
11447e946e7SWyllys Ingersoll 	temp = temp->prev;
11547e946e7SWyllys Ingersoll 
11647e946e7SWyllys Ingersoll 	return (temp);
11747e946e7SWyllys Ingersoll }
11847e946e7SWyllys Ingersoll 
11947e946e7SWyllys Ingersoll 
12047e946e7SWyllys Ingersoll // Function:  dlist_get_last()
12147e946e7SWyllys Ingersoll //
12247e946e7SWyllys Ingersoll // Returns the last node in the list or NULL if list is empty
12347e946e7SWyllys Ingersoll //
12447e946e7SWyllys Ingersoll DL_NODE *
dlist_get_last(DL_NODE * list)12547e946e7SWyllys Ingersoll dlist_get_last(DL_NODE *list) {
12647e946e7SWyllys Ingersoll 	DL_NODE *temp = list;
12747e946e7SWyllys Ingersoll 
12847e946e7SWyllys Ingersoll 	if (! list)
12947e946e7SWyllys Ingersoll 		return (NULL);
13047e946e7SWyllys Ingersoll 	while (temp->next != NULL)
13147e946e7SWyllys Ingersoll 	temp = temp->next;
13247e946e7SWyllys Ingersoll 
13347e946e7SWyllys Ingersoll 	return (temp);
13447e946e7SWyllys Ingersoll }
13547e946e7SWyllys Ingersoll 
13647e946e7SWyllys Ingersoll 
13747e946e7SWyllys Ingersoll //
13847e946e7SWyllys Ingersoll //
13947e946e7SWyllys Ingersoll CK_ULONG
dlist_length(DL_NODE * list)14047e946e7SWyllys Ingersoll dlist_length(DL_NODE *list) {
14147e946e7SWyllys Ingersoll 	DL_NODE  *temp = list;
14247e946e7SWyllys Ingersoll 	CK_ULONG  len  = 0;
14347e946e7SWyllys Ingersoll 
14447e946e7SWyllys Ingersoll 	while (temp) {
14547e946e7SWyllys Ingersoll 		len++;
14647e946e7SWyllys Ingersoll 		temp = temp->next;
14747e946e7SWyllys Ingersoll 	}
14847e946e7SWyllys Ingersoll 
14947e946e7SWyllys Ingersoll 	return (len);
15047e946e7SWyllys Ingersoll }
15147e946e7SWyllys Ingersoll 
15247e946e7SWyllys Ingersoll 
15347e946e7SWyllys Ingersoll //
15447e946e7SWyllys Ingersoll //
15547e946e7SWyllys Ingersoll DL_NODE *
dlist_next(DL_NODE * node)15647e946e7SWyllys Ingersoll dlist_next(DL_NODE *node)
15747e946e7SWyllys Ingersoll {
15847e946e7SWyllys Ingersoll 	if (! node)
15947e946e7SWyllys Ingersoll 		return (NULL);
16047e946e7SWyllys Ingersoll 	return (node->next);
16147e946e7SWyllys Ingersoll }
16247e946e7SWyllys Ingersoll 
16347e946e7SWyllys Ingersoll 
16447e946e7SWyllys Ingersoll //
16547e946e7SWyllys Ingersoll //
16647e946e7SWyllys Ingersoll DL_NODE *
dlist_prev(DL_NODE * node)16747e946e7SWyllys Ingersoll dlist_prev(DL_NODE *node) {
16847e946e7SWyllys Ingersoll 	if (! node)
16947e946e7SWyllys Ingersoll 		return (NULL);
17047e946e7SWyllys Ingersoll 	return (node->prev);
17147e946e7SWyllys Ingersoll }
17247e946e7SWyllys Ingersoll 
17347e946e7SWyllys Ingersoll 
17447e946e7SWyllys Ingersoll //
17547e946e7SWyllys Ingersoll //
17647e946e7SWyllys Ingersoll void
dlist_purge(DL_NODE * list)17747e946e7SWyllys Ingersoll dlist_purge(DL_NODE *list) {
17847e946e7SWyllys Ingersoll 	DL_NODE *node;
17947e946e7SWyllys Ingersoll 
18047e946e7SWyllys Ingersoll 	if (! list)
18147e946e7SWyllys Ingersoll 		return;
18247e946e7SWyllys Ingersoll 	do {
18347e946e7SWyllys Ingersoll 		node = list->next;
18447e946e7SWyllys Ingersoll 		free(list);
18547e946e7SWyllys Ingersoll 		list = node;
18647e946e7SWyllys Ingersoll 	} while (list);
18747e946e7SWyllys Ingersoll }
18847e946e7SWyllys Ingersoll 
18947e946e7SWyllys Ingersoll // Function:  dlist_remove_node()
19047e946e7SWyllys Ingersoll //
19147e946e7SWyllys Ingersoll // Attempts to remove the specified node from the list.  The caller is
19247e946e7SWyllys Ingersoll // responsible for freeing the data associated with the node prior to
19347e946e7SWyllys Ingersoll // calling this routine
19447e946e7SWyllys Ingersoll //
19547e946e7SWyllys Ingersoll DL_NODE *
dlist_remove_node(DL_NODE * list,DL_NODE * node)19647e946e7SWyllys Ingersoll dlist_remove_node(DL_NODE *list, DL_NODE *node) {
19747e946e7SWyllys Ingersoll 	DL_NODE *temp  = list;
19847e946e7SWyllys Ingersoll 
19947e946e7SWyllys Ingersoll 	if (! list || ! node)
20047e946e7SWyllys Ingersoll 		return (NULL);
20147e946e7SWyllys Ingersoll 	// special case:  removing head of the list
20247e946e7SWyllys Ingersoll 	//
20347e946e7SWyllys Ingersoll 	if (list == node) {
20447e946e7SWyllys Ingersoll 		temp = list->next;
20547e946e7SWyllys Ingersoll 		if (temp)
20647e946e7SWyllys Ingersoll 			temp->prev = NULL;
20747e946e7SWyllys Ingersoll 
20847e946e7SWyllys Ingersoll 		free(list);
20947e946e7SWyllys Ingersoll 		return (temp);
21047e946e7SWyllys Ingersoll 	}
21147e946e7SWyllys Ingersoll 
21247e946e7SWyllys Ingersoll 	// we have no guarantee that the node is in the list
21347e946e7SWyllys Ingersoll 	// so search through the list to find it
21447e946e7SWyllys Ingersoll 	//
21547e946e7SWyllys Ingersoll 	while ((temp != NULL) && (temp->next != node))
21647e946e7SWyllys Ingersoll 	temp = temp->next;
21747e946e7SWyllys Ingersoll 
21847e946e7SWyllys Ingersoll 	if (temp != NULL) {
21947e946e7SWyllys Ingersoll 		DL_NODE *next = node->next;
22047e946e7SWyllys Ingersoll 
22147e946e7SWyllys Ingersoll 		temp->next = next;
22247e946e7SWyllys Ingersoll 		if (next)
22347e946e7SWyllys Ingersoll 			next->prev = temp;
22447e946e7SWyllys Ingersoll 
22547e946e7SWyllys Ingersoll 		free(node);
22647e946e7SWyllys Ingersoll 	}
22747e946e7SWyllys Ingersoll 
22847e946e7SWyllys Ingersoll 	return (list);
22947e946e7SWyllys Ingersoll }
23047e946e7SWyllys Ingersoll 
23147e946e7SWyllys Ingersoll extern void set_perm(int);
23247e946e7SWyllys Ingersoll 
23347e946e7SWyllys Ingersoll void
CreateXProcLock(void * xproc)23447e946e7SWyllys Ingersoll CreateXProcLock(void *xproc)
23547e946e7SWyllys Ingersoll {
23647e946e7SWyllys Ingersoll 	pthread_mutexattr_t  mtxattr;
23747e946e7SWyllys Ingersoll 
23847e946e7SWyllys Ingersoll 	(void) pthread_mutexattr_init(&mtxattr);
23947e946e7SWyllys Ingersoll 	(void) pthread_mutexattr_setpshared(&mtxattr, PTHREAD_PROCESS_SHARED);
24047e946e7SWyllys Ingersoll 	(void) pthread_mutex_init((pthread_mutex_t *)xproc, &mtxattr);
24147e946e7SWyllys Ingersoll }
24247e946e7SWyllys Ingersoll 
24347e946e7SWyllys Ingersoll int
DestroyXProcLock(void * xproc)24447e946e7SWyllys Ingersoll DestroyXProcLock(void *xproc)
24547e946e7SWyllys Ingersoll {
24647e946e7SWyllys Ingersoll 	return (pthread_mutex_destroy((pthread_mutex_t *)xproc));
24747e946e7SWyllys Ingersoll }
24847e946e7SWyllys Ingersoll 
24947e946e7SWyllys Ingersoll int
XProcLock(void * xproc)25047e946e7SWyllys Ingersoll XProcLock(void *xproc)
25147e946e7SWyllys Ingersoll {
25247e946e7SWyllys Ingersoll 	return (pthread_mutex_lock((pthread_mutex_t *)xproc));
25347e946e7SWyllys Ingersoll }
25447e946e7SWyllys Ingersoll 
25547e946e7SWyllys Ingersoll int
XProcUnLock(void * xproc)25647e946e7SWyllys Ingersoll XProcUnLock(void *xproc)
25747e946e7SWyllys Ingersoll {
25847e946e7SWyllys Ingersoll 	return (pthread_mutex_unlock((pthread_mutex_t *)xproc));
25947e946e7SWyllys Ingersoll }
26047e946e7SWyllys Ingersoll 
26147e946e7SWyllys Ingersoll //
26247e946e7SWyllys Ingersoll //
26347e946e7SWyllys Ingersoll // is_attribute_defined()
26447e946e7SWyllys Ingersoll //
26547e946e7SWyllys Ingersoll // determine whether the specified attribute is defined by Cryptoki
26647e946e7SWyllys Ingersoll //
26747e946e7SWyllys Ingersoll CK_BBOOL
is_attribute_defined(CK_ATTRIBUTE_TYPE type)26847e946e7SWyllys Ingersoll is_attribute_defined(CK_ATTRIBUTE_TYPE type)
26947e946e7SWyllys Ingersoll {
27047e946e7SWyllys Ingersoll 	if (type >= CKA_VENDOR_DEFINED)
27147e946e7SWyllys Ingersoll 		return (TRUE);
27247e946e7SWyllys Ingersoll 	switch (type) {
27347e946e7SWyllys Ingersoll 		case  CKA_CLASS:
27447e946e7SWyllys Ingersoll 		case  CKA_TOKEN:
27547e946e7SWyllys Ingersoll 		case  CKA_PRIVATE:
27647e946e7SWyllys Ingersoll 		case  CKA_LABEL:
27747e946e7SWyllys Ingersoll 		case  CKA_APPLICATION:
27847e946e7SWyllys Ingersoll 		case  CKA_VALUE:
27947e946e7SWyllys Ingersoll 		case  CKA_CERTIFICATE_TYPE:
28047e946e7SWyllys Ingersoll 		case  CKA_ISSUER:
28147e946e7SWyllys Ingersoll 		case  CKA_SERIAL_NUMBER:
28247e946e7SWyllys Ingersoll 		case  CKA_KEY_TYPE:
28347e946e7SWyllys Ingersoll 		case  CKA_SUBJECT:
28447e946e7SWyllys Ingersoll 		case  CKA_ID:
28547e946e7SWyllys Ingersoll 		case  CKA_SENSITIVE:
28647e946e7SWyllys Ingersoll 		case  CKA_ENCRYPT:
28747e946e7SWyllys Ingersoll 		case  CKA_DECRYPT:
28847e946e7SWyllys Ingersoll 		case  CKA_WRAP:
28947e946e7SWyllys Ingersoll 		case  CKA_UNWRAP:
29047e946e7SWyllys Ingersoll 		case  CKA_SIGN:
29147e946e7SWyllys Ingersoll 		case  CKA_SIGN_RECOVER:
29247e946e7SWyllys Ingersoll 		case  CKA_VERIFY:
29347e946e7SWyllys Ingersoll 		case  CKA_VERIFY_RECOVER:
29447e946e7SWyllys Ingersoll 		case  CKA_DERIVE:
29547e946e7SWyllys Ingersoll 		case  CKA_START_DATE:
29647e946e7SWyllys Ingersoll 		case  CKA_END_DATE:
29747e946e7SWyllys Ingersoll 		case  CKA_MODULUS:
29847e946e7SWyllys Ingersoll 		case  CKA_MODULUS_BITS:
29947e946e7SWyllys Ingersoll 		case  CKA_PUBLIC_EXPONENT:
30047e946e7SWyllys Ingersoll 		case  CKA_PRIVATE_EXPONENT:
30147e946e7SWyllys Ingersoll 		case  CKA_PRIME_1:
30247e946e7SWyllys Ingersoll 		case  CKA_PRIME_2:
30347e946e7SWyllys Ingersoll 		case  CKA_EXPONENT_1:
30447e946e7SWyllys Ingersoll 		case  CKA_EXPONENT_2:
30547e946e7SWyllys Ingersoll 		case  CKA_COEFFICIENT:
30647e946e7SWyllys Ingersoll 		case  CKA_PRIME:
30747e946e7SWyllys Ingersoll 		case  CKA_SUBPRIME:
30847e946e7SWyllys Ingersoll 		case  CKA_BASE:
30947e946e7SWyllys Ingersoll 		case  CKA_VALUE_BITS:
31047e946e7SWyllys Ingersoll 		case  CKA_VALUE_LEN:
31147e946e7SWyllys Ingersoll 		case  CKA_EXTRACTABLE:
31247e946e7SWyllys Ingersoll 		case  CKA_LOCAL:
31347e946e7SWyllys Ingersoll 		case  CKA_NEVER_EXTRACTABLE:
31447e946e7SWyllys Ingersoll 		case  CKA_ALWAYS_SENSITIVE:
31547e946e7SWyllys Ingersoll 		case  CKA_MODIFIABLE:
31647e946e7SWyllys Ingersoll 		case  CKA_ECDSA_PARAMS:
31747e946e7SWyllys Ingersoll 		case  CKA_EC_POINT:
31847e946e7SWyllys Ingersoll 		case  CKA_HW_FEATURE_TYPE:
31947e946e7SWyllys Ingersoll 		case  CKA_HAS_RESET:
32047e946e7SWyllys Ingersoll 		case  CKA_RESET_ON_INIT:
32147e946e7SWyllys Ingersoll 		case  CKA_KEY_GEN_MECHANISM:
32247e946e7SWyllys Ingersoll 		case  CKA_PRIME_BITS:
32347e946e7SWyllys Ingersoll 		case  CKA_SUBPRIME_BITS:
32447e946e7SWyllys Ingersoll 		case  CKA_OBJECT_ID:
32547e946e7SWyllys Ingersoll 		case  CKA_AC_ISSUER:
32647e946e7SWyllys Ingersoll 		case  CKA_OWNER:
32747e946e7SWyllys Ingersoll 		case  CKA_ATTR_TYPES:
32847e946e7SWyllys Ingersoll 		case  CKA_TRUSTED:
32947e946e7SWyllys Ingersoll 		return (TRUE);
33047e946e7SWyllys Ingersoll 	}
33147e946e7SWyllys Ingersoll 
33247e946e7SWyllys Ingersoll 	return (FALSE);
33347e946e7SWyllys Ingersoll }
33447e946e7SWyllys Ingersoll 
33547e946e7SWyllys Ingersoll void
init_slot_info(TOKEN_DATA * td)33647e946e7SWyllys Ingersoll init_slot_info(TOKEN_DATA *td)
33747e946e7SWyllys Ingersoll {
33847e946e7SWyllys Ingersoll 	/*
33947e946e7SWyllys Ingersoll 	 * Much of the token info is pulled from the TPM itself when
34047e946e7SWyllys Ingersoll 	 * C_Initialize is called.
34147e946e7SWyllys Ingersoll 	 */
34247e946e7SWyllys Ingersoll 	(void) (void) memset(&slot_info.slotDescription, ' ',
34347e946e7SWyllys Ingersoll 	    sizeof (slot_info.slotDescription) - 1);
34447e946e7SWyllys Ingersoll 	(void) (void) memset(&slot_info.manufacturerID,  ' ',
34547e946e7SWyllys Ingersoll 	    sizeof (slot_info.manufacturerID) - 1);
34647e946e7SWyllys Ingersoll 
34747e946e7SWyllys Ingersoll 	(void) (void) memcpy(&slot_info.slotDescription,
34847e946e7SWyllys Ingersoll 	    "PKCS#11 Interface for TPM",
34947e946e7SWyllys Ingersoll 	    strlen("PKCS#11 Interface for TPM"));
35047e946e7SWyllys Ingersoll 
35147e946e7SWyllys Ingersoll 	(void) (void) memcpy(&slot_info.manufacturerID,
35247e946e7SWyllys Ingersoll 	    td->token_info.manufacturerID,
35347e946e7SWyllys Ingersoll 	    strlen((char *)td->token_info.manufacturerID));
35447e946e7SWyllys Ingersoll 
35547e946e7SWyllys Ingersoll 	slot_info.hardwareVersion = nv_token_data->token_info.hardwareVersion;
35647e946e7SWyllys Ingersoll 	slot_info.firmwareVersion = nv_token_data->token_info.firmwareVersion;
35747e946e7SWyllys Ingersoll 	slot_info.flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT;
35847e946e7SWyllys Ingersoll }
35947e946e7SWyllys Ingersoll 
36047e946e7SWyllys Ingersoll /*ARGSUSED*/
36147e946e7SWyllys Ingersoll void
copy_slot_info(CK_SLOT_ID slotID,CK_SLOT_INFO_PTR sinfo)36247e946e7SWyllys Ingersoll copy_slot_info(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR sinfo)
36347e946e7SWyllys Ingersoll {
36447e946e7SWyllys Ingersoll 	if (sinfo != NULL)
36547e946e7SWyllys Ingersoll 		(void) memcpy(sinfo, &slot_info, sizeof (slot_info));
36647e946e7SWyllys Ingersoll }
36747e946e7SWyllys Ingersoll 
36847e946e7SWyllys Ingersoll static void
init_token_info(TOKEN_DATA * td)36947e946e7SWyllys Ingersoll init_token_info(TOKEN_DATA *td)
37047e946e7SWyllys Ingersoll {
37147e946e7SWyllys Ingersoll 	CK_TOKEN_INFO    *token_info = NULL;
37247e946e7SWyllys Ingersoll 
37347e946e7SWyllys Ingersoll 	token_info = &td->token_info;
37447e946e7SWyllys Ingersoll 
37547e946e7SWyllys Ingersoll 	(void) memset(token_info->model, ' ',
37647e946e7SWyllys Ingersoll 	    sizeof (token_info->model));
37747e946e7SWyllys Ingersoll 	(void) memset(token_info->serialNumber, ' ',
37847e946e7SWyllys Ingersoll 	    sizeof (token_info->serialNumber));
37947e946e7SWyllys Ingersoll 
38047e946e7SWyllys Ingersoll 	//
38147e946e7SWyllys Ingersoll 	// I don't see any API support for changing the clock so
38247e946e7SWyllys Ingersoll 	// we will use the system clock for the token's clock.
38347e946e7SWyllys Ingersoll 	//
38447e946e7SWyllys Ingersoll 	token_info->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_CLOCK_ON_TOKEN |
38547e946e7SWyllys Ingersoll 	    CKF_SO_PIN_TO_BE_CHANGED;
38647e946e7SWyllys Ingersoll 
38747e946e7SWyllys Ingersoll 	if (memcmp(td->user_pin_sha, "00000000000000000000",
38847e946e7SWyllys Ingersoll 	    SHA1_DIGEST_LENGTH) != 0)
38947e946e7SWyllys Ingersoll 		token_info->flags |= CKF_USER_PIN_INITIALIZED;
39047e946e7SWyllys Ingersoll 	else
39147e946e7SWyllys Ingersoll 		token_info->flags |= CKF_USER_PIN_TO_BE_CHANGED;
39247e946e7SWyllys Ingersoll 
39347e946e7SWyllys Ingersoll 	// For the release, we made these
39447e946e7SWyllys Ingersoll 	// values as CK_UNAVAILABLE_INFORMATION
39547e946e7SWyllys Ingersoll 	//
39647e946e7SWyllys Ingersoll 	token_info->ulMaxSessionCount    = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
39747e946e7SWyllys Ingersoll 	token_info->ulSessionCount	= (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
39847e946e7SWyllys Ingersoll 	token_info->ulMaxRwSessionCount  = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
39947e946e7SWyllys Ingersoll 	token_info->ulRwSessionCount	= (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
40047e946e7SWyllys Ingersoll 	token_info->ulMaxPinLen	  = MAX_PIN_LEN;
40147e946e7SWyllys Ingersoll 	token_info->ulMinPinLen	  = MIN_PIN_LEN;
40247e946e7SWyllys Ingersoll 	token_info->ulTotalPublicMemory  = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
40347e946e7SWyllys Ingersoll 	token_info->ulFreePublicMemory   = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
40447e946e7SWyllys Ingersoll 	token_info->ulTotalPrivateMemory = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
40547e946e7SWyllys Ingersoll 	token_info->ulFreePrivateMemory  = (CK_ULONG)CK_UNAVAILABLE_INFORMATION;
40647e946e7SWyllys Ingersoll 
40747e946e7SWyllys Ingersoll 	(void) memset(token_info->utcTime, ' ', sizeof (token_info->utcTime));
40847e946e7SWyllys Ingersoll }
40947e946e7SWyllys Ingersoll 
41047e946e7SWyllys Ingersoll CK_RV
init_token_data(TSS_HCONTEXT hContext,TOKEN_DATA * td)41147e946e7SWyllys Ingersoll init_token_data(TSS_HCONTEXT hContext, TOKEN_DATA *td) {
41247e946e7SWyllys Ingersoll 	CK_RV rc;
41347e946e7SWyllys Ingersoll 
41447e946e7SWyllys Ingersoll 	(void) memset((char *)td, 0, sizeof (nv_token_data));
41547e946e7SWyllys Ingersoll 	//
41647e946e7SWyllys Ingersoll 	// the normal USER pin is not set when the token is initialized
41747e946e7SWyllys Ingersoll 	//
41847e946e7SWyllys Ingersoll 	(void) memcpy(td->user_pin_sha, "00000000000000000000",
41947e946e7SWyllys Ingersoll 	    SHA1_DIGEST_LENGTH);
42047e946e7SWyllys Ingersoll 	(void) memcpy(td->so_pin_sha, default_so_pin_sha,
42147e946e7SWyllys Ingersoll 	    SHA1_DIGEST_LENGTH);
42247e946e7SWyllys Ingersoll 
42347e946e7SWyllys Ingersoll 	(void) memset(user_pin_md5, 0x0, MD5_DIGEST_LENGTH);
42447e946e7SWyllys Ingersoll 	(void) memcpy(so_pin_md5, default_so_pin_md5, MD5_DIGEST_LENGTH);
42547e946e7SWyllys Ingersoll 
42647e946e7SWyllys Ingersoll 	(void) memcpy(td->next_token_object_name, "00000000", 8);
42747e946e7SWyllys Ingersoll 
42847e946e7SWyllys Ingersoll 	td->tweak_vector.allow_key_mods   = TRUE;
42947e946e7SWyllys Ingersoll 
43047e946e7SWyllys Ingersoll 	init_token_info(td);
43147e946e7SWyllys Ingersoll 
43247e946e7SWyllys Ingersoll 	rc = token_get_tpm_info(hContext, td);
43347e946e7SWyllys Ingersoll 	if (rc != CKR_OK)
43447e946e7SWyllys Ingersoll 		return (rc);
43547e946e7SWyllys Ingersoll 
43647e946e7SWyllys Ingersoll 	rc = save_token_data(td);
43747e946e7SWyllys Ingersoll 
43847e946e7SWyllys Ingersoll 	return (rc);
43947e946e7SWyllys Ingersoll }
44047e946e7SWyllys Ingersoll 
44147e946e7SWyllys Ingersoll // Function:  compute_next_token_obj_name()
44247e946e7SWyllys Ingersoll //
44347e946e7SWyllys Ingersoll // Given a token object name (8 bytes in the range [0 - 9A - Z])
44447e946e7SWyllys Ingersoll // increment by one adjusting as necessary
44547e946e7SWyllys Ingersoll //
44647e946e7SWyllys Ingersoll // This gives us a namespace of 36^8 = 2, 821, 109, 907, 456
44747e946e7SWyllys Ingersoll // objects before wrapping around.
44847e946e7SWyllys Ingersoll //
44947e946e7SWyllys Ingersoll CK_RV
compute_next_token_obj_name(CK_BYTE * current,CK_BYTE * next)45047e946e7SWyllys Ingersoll compute_next_token_obj_name(CK_BYTE *current, CK_BYTE *next) {
45147e946e7SWyllys Ingersoll 	int val[8];
45247e946e7SWyllys Ingersoll 	int i;
45347e946e7SWyllys Ingersoll 
45447e946e7SWyllys Ingersoll 	if (! current || ! next) {
45547e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
45647e946e7SWyllys Ingersoll 	}
45747e946e7SWyllys Ingersoll 	// Convert to integral base 36
45847e946e7SWyllys Ingersoll 	//
45947e946e7SWyllys Ingersoll 	for (i = 0; i < 8; i++) {
46047e946e7SWyllys Ingersoll 		if (current[i] >= '0' && current[i] <= '9')
46147e946e7SWyllys Ingersoll 			val[i] = current[i] - '0';
46247e946e7SWyllys Ingersoll 
46347e946e7SWyllys Ingersoll 		if (current[i] >= 'A' && current[i] <= 'Z')
46447e946e7SWyllys Ingersoll 			val[i] = current[i] - 'A' + 10;
46547e946e7SWyllys Ingersoll 	}
46647e946e7SWyllys Ingersoll 
46747e946e7SWyllys Ingersoll 	val[0]++;
46847e946e7SWyllys Ingersoll 
46947e946e7SWyllys Ingersoll 	i = 0;
47047e946e7SWyllys Ingersoll 
47147e946e7SWyllys Ingersoll 	while (val[i] > 35) {
47247e946e7SWyllys Ingersoll 		val[i] = 0;
47347e946e7SWyllys Ingersoll 
47447e946e7SWyllys Ingersoll 		if (i + 1 < 8) {
47547e946e7SWyllys Ingersoll 			val[i + 1]++;
47647e946e7SWyllys Ingersoll 			i++;
47747e946e7SWyllys Ingersoll 		} else {
47847e946e7SWyllys Ingersoll 			val[0]++;
47947e946e7SWyllys Ingersoll 			i = 0;   // start pass 2
48047e946e7SWyllys Ingersoll 		}
48147e946e7SWyllys Ingersoll 	}
48247e946e7SWyllys Ingersoll 
48347e946e7SWyllys Ingersoll 	// now, convert back to [0 - 9A - Z]
48447e946e7SWyllys Ingersoll 	//
48547e946e7SWyllys Ingersoll 	for (i = 0; i < 8; i++) {
48647e946e7SWyllys Ingersoll 		if (val[i] < 10)
48747e946e7SWyllys Ingersoll 			next[i] = '0' + val[i];
48847e946e7SWyllys Ingersoll 		else
48947e946e7SWyllys Ingersoll 			next[i] = 'A' + val[i] - 10;
49047e946e7SWyllys Ingersoll 	}
49147e946e7SWyllys Ingersoll 
49247e946e7SWyllys Ingersoll 	return (CKR_OK);
49347e946e7SWyllys Ingersoll }
49447e946e7SWyllys Ingersoll 
49547e946e7SWyllys Ingersoll 
49647e946e7SWyllys Ingersoll //
49747e946e7SWyllys Ingersoll //
49847e946e7SWyllys Ingersoll CK_RV
build_attribute(CK_ATTRIBUTE_TYPE type,CK_BYTE * data,CK_ULONG data_len,CK_ATTRIBUTE ** attrib)49947e946e7SWyllys Ingersoll build_attribute(CK_ATTRIBUTE_TYPE  type,
50047e946e7SWyllys Ingersoll 	CK_BYTE	   *data,
50147e946e7SWyllys Ingersoll 	CK_ULONG	   data_len,
50247e946e7SWyllys Ingersoll 	CK_ATTRIBUTE	**attrib) {
50347e946e7SWyllys Ingersoll 	CK_ATTRIBUTE *attr = NULL;
50447e946e7SWyllys Ingersoll 
50547e946e7SWyllys Ingersoll 	attr = (CK_ATTRIBUTE *)malloc(sizeof (CK_ATTRIBUTE) + data_len);
50647e946e7SWyllys Ingersoll 	if (! attr) {
50747e946e7SWyllys Ingersoll 		return (CKR_DEVICE_MEMORY);
50847e946e7SWyllys Ingersoll 	}
50947e946e7SWyllys Ingersoll 	attr->type  = type;
51047e946e7SWyllys Ingersoll 	attr->ulValueLen = data_len;
51147e946e7SWyllys Ingersoll 
51247e946e7SWyllys Ingersoll 	if (data_len > 0) {
51347e946e7SWyllys Ingersoll 		attr->pValue = (CK_BYTE *)attr + sizeof (CK_ATTRIBUTE);
51447e946e7SWyllys Ingersoll 		(void) memcpy(attr->pValue, data, data_len);
51547e946e7SWyllys Ingersoll 	}
51647e946e7SWyllys Ingersoll 	else
51747e946e7SWyllys Ingersoll 		attr->pValue = NULL;
51847e946e7SWyllys Ingersoll 
51947e946e7SWyllys Ingersoll 	 *attrib = attr;
52047e946e7SWyllys Ingersoll 
52147e946e7SWyllys Ingersoll 	return (CKR_OK);
52247e946e7SWyllys Ingersoll }
52347e946e7SWyllys Ingersoll 
52447e946e7SWyllys Ingersoll CK_RV
add_pkcs_padding(CK_BYTE * ptr,UINT32 block_size,UINT32 data_len,UINT32 total_len)52547e946e7SWyllys Ingersoll add_pkcs_padding(CK_BYTE  * ptr,
52633c15889SWyllys Ingersoll 	UINT32   block_size,
52733c15889SWyllys Ingersoll 	UINT32   data_len,
52833c15889SWyllys Ingersoll 	UINT32   total_len)
52947e946e7SWyllys Ingersoll {
53033c15889SWyllys Ingersoll 	UINT32 i, pad_len;
53147e946e7SWyllys Ingersoll 	CK_BYTE  pad_value;
53247e946e7SWyllys Ingersoll 
53347e946e7SWyllys Ingersoll 	pad_len = block_size - (data_len % block_size);
53447e946e7SWyllys Ingersoll 	pad_value = (CK_BYTE)pad_len;
53547e946e7SWyllys Ingersoll 
53647e946e7SWyllys Ingersoll 	if (data_len + pad_len > total_len) {
53747e946e7SWyllys Ingersoll 		return (CKR_FUNCTION_FAILED);
53847e946e7SWyllys Ingersoll 	}
53947e946e7SWyllys Ingersoll 	for (i = 0; i < pad_len; i++)
54033c15889SWyllys Ingersoll 		ptr[i] = pad_value;
54147e946e7SWyllys Ingersoll 
54247e946e7SWyllys Ingersoll 	return (CKR_OK);
54347e946e7SWyllys Ingersoll }
54447e946e7SWyllys Ingersoll 
54547e946e7SWyllys Ingersoll CK_RV
strip_pkcs_padding(CK_BYTE * ptr,UINT32 total_len,UINT32 * data_len)54633c15889SWyllys Ingersoll strip_pkcs_padding(
54733c15889SWyllys Ingersoll 	CK_BYTE *ptr,
54833c15889SWyllys Ingersoll 	UINT32  total_len,
54933c15889SWyllys Ingersoll 	UINT32  *data_len)
55033c15889SWyllys Ingersoll {
55147e946e7SWyllys Ingersoll 	CK_BYTE  pad_value;
55247e946e7SWyllys Ingersoll 
55347e946e7SWyllys Ingersoll 	pad_value = ptr[total_len - 1];
55447e946e7SWyllys Ingersoll 
55533c15889SWyllys Ingersoll 	/* We have 'pad_value' bytes of 'pad_value' appended to the end */
55633c15889SWyllys Ingersoll 	*data_len = total_len - pad_value;
55747e946e7SWyllys Ingersoll 
55847e946e7SWyllys Ingersoll 	return (CKR_OK);
55947e946e7SWyllys Ingersoll }
56047e946e7SWyllys Ingersoll 
56147e946e7SWyllys Ingersoll CK_RV
remove_leading_zeros(CK_ATTRIBUTE * attr)56247e946e7SWyllys Ingersoll remove_leading_zeros(CK_ATTRIBUTE *attr)
56347e946e7SWyllys Ingersoll {
56447e946e7SWyllys Ingersoll 	CK_BYTE   *ptr = NULL;
56547e946e7SWyllys Ingersoll 	CK_ULONG   new_len, i;
56647e946e7SWyllys Ingersoll 
56747e946e7SWyllys Ingersoll 	ptr = attr->pValue;
56847e946e7SWyllys Ingersoll 
56947e946e7SWyllys Ingersoll 	for (i = 0; i < attr->ulValueLen; i++) {
57047e946e7SWyllys Ingersoll 		if (ptr[i] != 0x0)
57147e946e7SWyllys Ingersoll 			break;
57247e946e7SWyllys Ingersoll 	}
57347e946e7SWyllys Ingersoll 
57447e946e7SWyllys Ingersoll 	new_len = attr->ulValueLen - i;
57547e946e7SWyllys Ingersoll 
57647e946e7SWyllys Ingersoll 	(void) memcpy(ptr, ptr + i, new_len);
57747e946e7SWyllys Ingersoll 	attr->ulValueLen = new_len;
57847e946e7SWyllys Ingersoll 
57947e946e7SWyllys Ingersoll 	return (CKR_OK);
58047e946e7SWyllys Ingersoll }
58147e946e7SWyllys Ingersoll 
58247e946e7SWyllys Ingersoll CK_RV
parity_is_odd(CK_BYTE b)58347e946e7SWyllys Ingersoll parity_is_odd(CK_BYTE b) {
58447e946e7SWyllys Ingersoll 	b = ((b >> 4) ^ b) & 0x0f;
58547e946e7SWyllys Ingersoll 	b = ((b >> 2) ^ b) & 0x03;
58647e946e7SWyllys Ingersoll 	b = ((b >> 1) ^ b) & 0x01;
58747e946e7SWyllys Ingersoll 
58847e946e7SWyllys Ingersoll 	if (b == 1)
58947e946e7SWyllys Ingersoll 		return (TRUE);
59047e946e7SWyllys Ingersoll 	else
59147e946e7SWyllys Ingersoll 		return (FALSE);
59247e946e7SWyllys Ingersoll }
59347e946e7SWyllys Ingersoll 
59447e946e7SWyllys Ingersoll CK_RV
attach_shm()59547e946e7SWyllys Ingersoll attach_shm() {
59647e946e7SWyllys Ingersoll 	if (global_shm != NULL)
59747e946e7SWyllys Ingersoll 		return (CKR_OK);
59847e946e7SWyllys Ingersoll 
599*8d26100cSWyllys Ingersoll 	global_shm = (LW_SHM_TYPE *)calloc(1, sizeof (LW_SHM_TYPE));
60047e946e7SWyllys Ingersoll 	if (global_shm == NULL) {
60147e946e7SWyllys Ingersoll 		return (CKR_HOST_MEMORY);
60247e946e7SWyllys Ingersoll 	}
60347e946e7SWyllys Ingersoll 	CreateXProcLock(&global_shm->mutex);
60447e946e7SWyllys Ingersoll 
60547e946e7SWyllys Ingersoll 	xproclock = (void *)&global_shm->mutex;
60647e946e7SWyllys Ingersoll 
60747e946e7SWyllys Ingersoll 	return (CKR_OK);
60847e946e7SWyllys Ingersoll }
60947e946e7SWyllys Ingersoll 
61047e946e7SWyllys Ingersoll CK_RV
detach_shm()61147e946e7SWyllys Ingersoll detach_shm()
61247e946e7SWyllys Ingersoll {
61347e946e7SWyllys Ingersoll 	if (global_shm != NULL) {
61447e946e7SWyllys Ingersoll 		free(global_shm);
61547e946e7SWyllys Ingersoll 		global_shm = NULL;
61647e946e7SWyllys Ingersoll 	}
61747e946e7SWyllys Ingersoll 
61847e946e7SWyllys Ingersoll 	return (CKR_OK);
61947e946e7SWyllys Ingersoll }
62047e946e7SWyllys Ingersoll 
62147e946e7SWyllys Ingersoll CK_RV
compute_sha(CK_BYTE * data,CK_ULONG_32 len,CK_BYTE * hash)62247e946e7SWyllys Ingersoll compute_sha(CK_BYTE  *data,
62333c15889SWyllys Ingersoll 	CK_ULONG_32   len,
62447e946e7SWyllys Ingersoll 	CK_BYTE  * hash)
62547e946e7SWyllys Ingersoll {
62647e946e7SWyllys Ingersoll 	SHA1_CTX	ctx;
62747e946e7SWyllys Ingersoll 
62847e946e7SWyllys Ingersoll 	SHA1Init(&ctx);
62947e946e7SWyllys Ingersoll 
63047e946e7SWyllys Ingersoll 	SHA1Update(&ctx, data, len);
63147e946e7SWyllys Ingersoll 
63247e946e7SWyllys Ingersoll 	SHA1Final(hash, &ctx);
63347e946e7SWyllys Ingersoll 	return (CKR_OK);
63447e946e7SWyllys Ingersoll }
635