Diff

Differences From Artifact [47338c5b52]:

To Artifact [eb71775c47]:


     1         -#include "mypkcs11.h"
     2         -
     3      1   #include <sys/types.h>
     4      2   #include <string.h>
     5      3   #include <unistd.h>
     6      4   #include <stdlib.h>
     7      5   #include <stdio.h>
     8      6   
            7  +#ifndef CACKEY_TEST_AFL
            8  +#include "mypkcs11.h"
     9      9   
    10     10   static char *pkcs11_attribute_to_name(CK_ATTRIBUTE_TYPE attrib) {
    11     11   	static char retbuf[1024];
    12     12   
    13     13   	switch (attrib) {
    14     14   		case 0x00000000: return "CKA_CLASS";
    15     15   		case 0x00000001: return "CKA_TOKEN";
................................................................................
   616    616   	if (privateKeyObjects_root) {
   617    617   		free(privateKeyObjects_root);
   618    618   	}
   619    619   
   620    620   	return(0);
   621    621   }
   622    622   
   623         -int main(void) {
          623  +int main(int argc, char **argv) {
   624    624   	int retval = 0, ck_retval;
   625    625   
   626    626   	printf("Testing libcackey...\n");
   627    627   
   628    628   	ck_retval = main_pkcs11();
   629    629   
   630    630   	if (ck_retval != 0) {
   631    631   		retval = ck_retval;
   632    632   	}
   633    633   
   634    634   	printf("Testing libcackey... DONE. Status = %i\n", ck_retval);
          635  +
          636  +	return(retval);
          637  +
          638  +	/* UNREACHED: This is just to supress a warning about arguments to main we do not use. */
          639  +	argc = argc;
          640  +	argv = argv;
          641  +}
          642  +#else /* CACKEY_TEST_AFL */
          643  +#include <sys/stat.h>
          644  +#include <sys/types.h>
          645  +#include <fcntl.h>
          646  +
          647  +/* Include the CACKey source */
          648  +#include "cackey.c"
          649  +
          650  +/* Fake a smartcard */
          651  +static int scard_inTransaction = 0;
          652  +static LONG scard_protocol;
          653  +
          654  +PCSC_API LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) {
          655  +	CACKEY_DEBUG_PRINTF("Called");
          656  +
          657  +	*phContext = 42;
          658  +
          659  +	return(SCARD_S_SUCCESS);
          660  +}
          661  +
          662  +PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext) {
          663  +	CACKEY_DEBUG_PRINTF("Called");
          664  +
          665  +	if (hContext != 42) {
          666  +		return(SCARD_E_INVALID_HANDLE);
          667  +	}
          668  +
          669  +	return(SCARD_S_SUCCESS);
          670  +}
          671  +
          672  +PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders) {
          673  +	static char *readers = "READER0";
          674  +
          675  +	CACKEY_DEBUG_PRINTF("Called");
          676  +
          677  +	if (hContext != 42) {
          678  +		return(SCARD_E_INVALID_HANDLE);
          679  +	}
          680  +
          681  +	*pcchReaders = strlen(readers) + 1;
          682  +
          683  +	if (mszReaders == NULL) {
          684  +		return(SCARD_S_SUCCESS);
          685  +	}
          686  +
          687  +	memcpy(mszReaders, readers, *pcchReaders);
          688  +
          689  +	return(SCARD_S_SUCCESS);
          690  +}
          691  +
          692  +PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard) {
          693  +	CACKEY_DEBUG_PRINTF("Called");
          694  +
          695  +	if (hCard != 99) {
          696  +		return(SCARD_E_INVALID_HANDLE);
          697  +	}
          698  +
          699  +	if (scard_inTransaction) {
          700  +		return(SCARD_E_SHARING_VIOLATION);
          701  +	}
          702  +
          703  +	scard_inTransaction = 1;
          704  +
          705  +	return(SCARD_S_SUCCESS);
          706  +}
          707  +PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) {
          708  +	CACKEY_DEBUG_PRINTF("Called");
          709  +
          710  +	if (hCard != 99) {
          711  +		return(SCARD_E_INVALID_HANDLE);
          712  +	}
          713  +
          714  +	scard_inTransaction = 0;
          715  +
          716  +	return(SCARD_S_SUCCESS);
          717  +}
          718  +
          719  +PCSC_API LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) {
          720  +	LONG scardlistreaders_ret;
          721  +
          722  +	CACKEY_DEBUG_PRINTF("Called");
          723  +
          724  +	if (hCard != 99) {
          725  +		return(SCARD_E_INVALID_HANDLE);
          726  +	}
          727  +
          728  +	*pdwState = 0;
          729  +	scardlistreaders_ret = SCardListReaders(42, NULL, mszReaderName, pcchReaderLen);
          730  +	if (scardlistreaders_ret != SCARD_S_SUCCESS) {
          731  +		return(scardlistreaders_ret);
          732  +	}
          733  +
          734  +	*pdwProtocol = scard_protocol;
          735  +
          736  +	return(SCARD_S_SUCCESS);
          737  +}
          738  +
          739  +PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol) {
          740  +	CACKEY_DEBUG_PRINTF("Called");
          741  +
          742  +	if (hContext != 42) {
          743  +		return(SCARD_E_INVALID_HANDLE);
          744  +	}
          745  +
          746  +	if ((dwPreferredProtocols & SCARD_PROTOCOL_T0) == SCARD_PROTOCOL_T0) {
          747  +		*pdwActiveProtocol = SCARD_PROTOCOL_T0;
          748  +	} else {
          749  +		*pdwActiveProtocol = SCARD_PROTOCOL_T1;
          750  +	}
          751  +
          752  +	scard_protocol = *pdwActiveProtocol;
          753  +
          754  +	*phCard = 99;
          755  +
          756  +	return(SCARD_S_SUCCESS);
          757  +}
          758  +
          759  +PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) {
          760  +	CACKEY_DEBUG_PRINTF("Called");
          761  +
          762  +	if (hCard != 99) {
          763  +		return(SCARD_E_INVALID_HANDLE);
          764  +	}
          765  +
          766  +	return(SCARD_S_SUCCESS);
          767  +}
          768  +
          769  +PCSC_API LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol) {
          770  +	CACKEY_DEBUG_PRINTF("Called");
          771  +
          772  +	if (hCard != 99) {
          773  +		return(SCARD_E_INVALID_HANDLE);
          774  +	}
          775  +
          776  +	return(SCardConnect(42, NULL, dwShareMode, dwPreferredProtocols, NULL, pdwActiveProtocol));
          777  +}
          778  +
          779  +PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext) {
          780  +	CACKEY_DEBUG_PRINTF("Called");
          781  +
          782  +	if (hContext != 42) {
          783  +		return(SCARD_E_INVALID_HANDLE);
          784  +	}
          785  +
          786  +	return(SCARD_S_SUCCESS);
          787  +}
          788  +
          789  +PCSC_API LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength) {
          790  +	CACKEY_DEBUG_PRINTF("Called");
          791  +
          792  +	if (hCard != 99) {
          793  +		return(SCARD_E_INVALID_HANDLE);
          794  +	}
          795  +
          796  +	pbRecvBuffer[0] = 0x90;
          797  +	pbRecvBuffer[1] = 0x00;
          798  +
          799  +	*pcbRecvLength = 2;
          800  +
          801  +	return(SCARD_S_SUCCESS);
          802  +}
          803  +
          804  +/* American Fuzzy Lop testing program */
          805  +int main(int argc, char **argv) {
          806  +	CK_FUNCTION_LIST_PTR pFunctionList;
          807  +	CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession) = NULL;
          808  +	CK_RV (*C_Finalize)(CK_VOID_PTR pReserved) = NULL;
          809  +	CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) = NULL;
          810  +	CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession) = NULL;
          811  +	CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) = NULL;
          812  +	CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) = NULL;
          813  +	CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) = NULL;
          814  +	CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) = NULL;
          815  +	CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs) = NULL;
          816  +	CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) = NULL;
          817  +	CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession) = NULL;
          818  +	CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) = NULL;
          819  +	CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) = NULL;
          820  +	CK_C_INITIALIZE_ARGS initargs;
          821  +	CK_ULONG numSlots;
          822  +	CK_SLOT_ID_PTR slots = NULL;
          823  +	CK_TOKEN_INFO tokenInfo;
          824  +	CK_SESSION_HANDLE hSession;
          825  +	CK_OBJECT_HANDLE hObject, *privateKeyObjects_root = NULL, *privateKeyObjects, *currPrivKey;
          826  +	CK_ULONG ulObjectCount;
          827  +	CK_ATTRIBUTE template[] = {
          828  +	                           {CKA_CLASS, NULL, 0},
          829  +	                           {CKA_TOKEN, NULL, 0},
          830  +	                           {CKA_LABEL, NULL, 0},
          831  +	                           {CKA_PRIVATE, NULL, 0},
          832  +	                           {CKA_ID, NULL, 0},
          833  +	                           {CKA_SERIAL_NUMBER, NULL, 0},
          834  +	                           {CKA_SUBJECT, NULL, 0},
          835  +	                           {CKA_ISSUER, NULL, 0},
          836  +	                           {CKA_CERTIFICATE_TYPE, NULL, 0},
          837  +	                           {CKA_KEY_TYPE, NULL, 0},
          838  +	                           {CKA_SIGN, NULL, 0},
          839  +	                           {CKA_VALUE, NULL, 0},
          840  +				   {CKA_CERT_MD5_HASH, NULL, 0},
          841  +				   {CKA_CERT_SHA1_HASH, NULL, 0},
          842  +				   {CKA_TRUSTED, NULL, 0},
          843  +				   {CKA_TRUST_CLIENT_AUTH, NULL, 0},
          844  +				   {CKA_TRUST_CODE_SIGNING, NULL, 0},
          845  +				   {CKA_TRUST_CRL_SIGN, NULL, 0},
          846  +				   {CKA_TRUST_DATA_ENCIPHERMENT, NULL, 0},
          847  +				   {CKA_TRUST_DIGITAL_SIGNATURE, NULL, 0},
          848  +				   {CKA_TRUST_EMAIL_PROTECTION, NULL, 0},
          849  +				   {CKA_TRUST_KEY_AGREEMENT, NULL, 0},
          850  +				   {CKA_TRUST_KEY_CERT_SIGN, NULL, 0},
          851  +				   {CKA_TRUST_KEY_ENCIPHERMENT, NULL, 0},
          852  +				   {CKA_TRUST_NON_REPUDIATION, NULL, 0},
          853  +				   {CKA_TRUST_SERVER_AUTH, NULL, 0}
          854  +	                          }, *curr_attr;
          855  +	CK_ULONG curr_attr_idx;
          856  +	CK_ULONG byte_idx;
          857  +	CK_OBJECT_CLASS objectClass;
          858  +	CK_BYTE signature[1024];
          859  +	CK_ULONG signature_len;
          860  +	CK_MECHANISM mechanism = {CKM_RSA_PKCS, NULL, 0};
          861  +	CK_RV chk_rv;
          862  +	ssize_t read_ret;
          863  +	char data[8192], *fileName = NULL;
          864  +	unsigned long data_len;
          865  +	int fd;
          866  +	int i;
          867  +	int initialized = 0;
          868  +	int retval = 1;
          869  +
          870  +	fileName = argv[1];
          871  +	if (fileName == NULL) {
          872  +		goto cleanup;
          873  +	}
          874  +
          875  +	fd = open(fileName, O_RDONLY);
          876  +	if (fd < 0) {
          877  +		goto cleanup;
          878  +	}
          879  +
          880  +	read_ret = read(fd, data, sizeof(data));
          881  +	if (read_ret < 0) {
          882  +		goto cleanup;
          883  +	}
          884  +
          885  +	data_len = read_ret;
          886  +
          887  +	close(fd);
          888  +
          889  +	chk_rv = C_GetFunctionList(&pFunctionList);
          890  +	if (chk_rv != CKR_OK) {
          891  +		printf("C_GetFunctionList() failed.");
          892  +
          893  +		goto cleanup;
          894  +	}
          895  +
          896  +	C_CloseSession = pFunctionList->C_CloseSession;
          897  +	C_Finalize = pFunctionList->C_Finalize;
          898  +	C_FindObjects = pFunctionList->C_FindObjects;
          899  +	C_FindObjectsFinal = pFunctionList->C_FindObjectsFinal;
          900  +	C_FindObjectsInit = pFunctionList->C_FindObjectsInit;
          901  +	C_GetAttributeValue = pFunctionList->C_GetAttributeValue;
          902  +	C_GetSlotList = pFunctionList->C_GetSlotList;
          903  +	C_GetTokenInfo = pFunctionList->C_GetTokenInfo;
          904  +	C_Initialize = pFunctionList->C_Initialize;
          905  +	C_Login = pFunctionList->C_Login;
          906  +	C_OpenSession = pFunctionList->C_OpenSession;
          907  +	C_Sign = pFunctionList->C_Sign;
          908  +	C_SignInit = pFunctionList->C_SignInit;
          909  +
          910  +	privateKeyObjects = malloc(sizeof(*privateKeyObjects) * 1024);
          911  +	privateKeyObjects_root = privateKeyObjects;
          912  +	for (i = 0; i < 1024; i++) {
          913  +		privateKeyObjects[i] = CK_INVALID_HANDLE;
          914  +	}
          915  +
          916  +	initargs.CreateMutex = NULL;
          917  +	initargs.DestroyMutex = NULL;
          918  +	initargs.LockMutex = NULL;
          919  +	initargs.UnlockMutex = NULL;
          920  +	initargs.flags = CKF_OS_LOCKING_OK;
          921  +	initargs.pReserved = NULL;
          922  +
          923  +	chk_rv = C_Initialize(&initargs);
          924  +	if (chk_rv != CKR_OK) {
          925  +		initargs.CreateMutex = NULL;
          926  +		initargs.DestroyMutex = NULL;
          927  +		initargs.LockMutex = NULL;
          928  +		initargs.UnlockMutex = NULL;
          929  +		initargs.flags = 0;
          930  +		initargs.pReserved = NULL;
          931  +
          932  +		chk_rv = C_Initialize(&initargs);
          933  +		if (chk_rv != CKR_OK) {
          934  +			printf("C_Initialize() failed.");
          935  +
          936  +			goto cleanup;
          937  +		}
          938  +	}
          939  +
          940  +	initialized = 1;
          941  +
          942  +	chk_rv = C_GetSlotList(FALSE, NULL, &numSlots);
          943  +	if (chk_rv != CKR_OK) {
          944  +		goto cleanup;
          945  +	}
          946  +
          947  +	if (numSlots == 0) {
          948  +		goto cleanup;
          949  +	}
          950  +
          951  +	slots = malloc(sizeof(*slots) * numSlots);
          952  +
          953  +	if (slots == NULL) {
          954  +		goto cleanup;
          955  +	}
          956  +
          957  +	chk_rv = C_GetSlotList(FALSE, slots, &numSlots);
          958  +	if (chk_rv != CKR_OK) {
          959  +		goto cleanup;
          960  +	}
          961  +
          962  +	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
          963  +	if (chk_rv != CKR_OK) {
          964  +		goto cleanup;
          965  +	}
          966  +
          967  +	chk_rv = C_GetTokenInfo(slots[0], &tokenInfo);
          968  +	if (chk_rv != CKR_OK) {
          969  +		goto cleanup;
          970  +	}
          971  +
          972  +	if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED && (tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
          973  +		printf("Unable to login to card.\n");
          974  +
          975  +		goto cleanup;
          976  +	}
          977  +
          978  +	chk_rv = C_Login(hSession, CKU_USER, NULL, 0);
          979  +	if (chk_rv != CKR_OK) {
          980  +		printf("Login to device failed.\n");
          981  +
          982  +		goto cleanup;
          983  +	}
          984  +
          985  +	chk_rv = C_FindObjectsInit(hSession, NULL, 0);
          986  +	if (chk_rv != CKR_OK) {
          987  +		goto cleanup;
          988  +	}
          989  +
          990  +	while (1) {
          991  +		chk_rv = C_FindObjects(hSession, &hObject, 1, &ulObjectCount);
          992  +		if (chk_rv != CKR_OK) {
          993  +			printf("FindObjects() failed.\n");
          994  +			break;
          995  +		}
          996  +
          997  +		if (ulObjectCount == 0) {
          998  +			break;
          999  +		}
         1000  +
         1001  +		if (ulObjectCount != 1) {
         1002  +			printf("FindObjects() returned a weird number of objects.  Asked for 1, got %lu.\n", ulObjectCount);
         1003  +			break;
         1004  +		}
         1005  +
         1006  +		for (curr_attr_idx = 0; curr_attr_idx < (sizeof(template) / sizeof(template[0])); curr_attr_idx++) {
         1007  +			curr_attr = &template[curr_attr_idx];
         1008  +			if (curr_attr->pValue) {
         1009  +				free(curr_attr->pValue);
         1010  +			}
         1011  +
         1012  +			curr_attr->pValue = NULL;
         1013  +		}
         1014  +
         1015  +		chk_rv = C_GetAttributeValue(hSession, hObject, &template[0], sizeof(template) / sizeof(template[0]));
         1016  +		if (chk_rv == CKR_ATTRIBUTE_TYPE_INVALID || chk_rv == CKR_ATTRIBUTE_SENSITIVE || chk_rv == CKR_BUFFER_TOO_SMALL) {
         1017  +			chk_rv = CKR_OK;
         1018  +		}
         1019  +
         1020  +		if (chk_rv != CKR_OK) {
         1021  +			continue;
         1022  +		}
         1023  +
         1024  +		for (curr_attr_idx = 0; curr_attr_idx < (sizeof(template) / sizeof(template[0])); curr_attr_idx++) {
         1025  +			curr_attr = &template[curr_attr_idx];
         1026  +
         1027  +			if (((CK_LONG) curr_attr->ulValueLen) != ((CK_LONG) -1)) {
         1028  +				curr_attr->pValue = malloc(curr_attr->ulValueLen);
         1029  +			}
         1030  +		}
         1031  +
         1032  +		chk_rv = C_GetAttributeValue(hSession, hObject, &template[0], sizeof(template) / sizeof(template[0]));
         1033  +		if (chk_rv == CKR_OK || chk_rv == CKR_ATTRIBUTE_SENSITIVE || chk_rv == CKR_ATTRIBUTE_TYPE_INVALID || chk_rv == CKR_BUFFER_TOO_SMALL) {
         1034  +			for (curr_attr_idx = 0; curr_attr_idx < (sizeof(template) / sizeof(template[0])); curr_attr_idx++) {
         1035  +				curr_attr = &template[curr_attr_idx];
         1036  +
         1037  +				if (curr_attr->pValue) {
         1038  +					switch (curr_attr->type) {
         1039  +						case CKA_CLASS:
         1040  +							objectClass = *((CK_OBJECT_CLASS *) curr_attr->pValue);
         1041  +
         1042  +							if (objectClass == CKO_PRIVATE_KEY) {
         1043  +								*privateKeyObjects = hObject;
         1044  +								privateKeyObjects++;
         1045  +							}
         1046  +					}
         1047  +				} else {
         1048  +					free(curr_attr->pValue);
         1049  +					curr_attr->pValue = NULL;
         1050  +				}
         1051  +			}
         1052  +		} else {
         1053  +			printf("GetAttributeValue(hObject=%lu)/1 failed (rv = %lu).\n", (unsigned long) hObject, (unsigned long) chk_rv);
         1054  +		}
         1055  +
         1056  +	}
         1057  +
         1058  +	chk_rv = C_FindObjectsFinal(hSession);
         1059  +	if (chk_rv != CKR_OK) {
         1060  +		printf("FindObjectsFinal() failed.\n");
         1061  +	}
         1062  +
         1063  +	for (currPrivKey = privateKeyObjects_root; *currPrivKey != CK_INVALID_HANDLE; currPrivKey++) {
         1064  +		chk_rv = C_SignInit(hSession, &mechanism, *currPrivKey);
         1065  +		if (chk_rv == CKR_OK) {
         1066  +			signature_len = sizeof(signature);
         1067  +
         1068  +			chk_rv = C_Sign(hSession, (CK_BYTE_PTR) data, data_len, (CK_BYTE_PTR) &signature, &signature_len);
         1069  +			if (chk_rv == CKR_OK) {
         1070  +				printf("[%04lu/%02lx] Signature: ", (unsigned long) *currPrivKey, (unsigned long) mechanism.mechanism);
         1071  +
         1072  +				for (byte_idx = 0; byte_idx < signature_len; byte_idx++) {
         1073  +					printf("%02x ", (unsigned int) signature[byte_idx]);
         1074  +				}
         1075  +
         1076  +				printf("\n");
         1077  +			} else {
         1078  +				printf("Sign() failed.\n");
         1079  +			}
         1080  +		} else {
         1081  +			printf("SignInit() failed.\n");
         1082  +		}
         1083  +	}
         1084  +
         1085  +	chk_rv = C_CloseSession(hSession);
         1086  +	if (chk_rv != CKR_OK) {
         1087  +		printf("CloseSession failed.\n");
         1088  +	}
         1089  +
         1090  +	retval = 0;
         1091  +
         1092  +cleanup:
         1093  +	if (initialized) {
         1094  +		C_Finalize(NULL);
         1095  +	}
         1096  +
         1097  +	if (slots) {
         1098  +		free(slots);
         1099  +	}
         1100  +
         1101  +	if (privateKeyObjects_root) {
         1102  +		free(privateKeyObjects_root);
         1103  +	}
   635   1104   
   636   1105   	return(retval);
   637   1106   }
         1107  +#endif