コード例 #1
0
ファイル: esteid_sign.c プロジェクト: Krabi/idkaart_public
int EstEID_sighHashWindows(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) {
	CK_SESSION_HANDLE session = 0L;
	char message[1024];
	int remainingTries = 0;	
	CK_RV loginResult = CKR_FUNCTION_CANCELED;
	
	LOG_LOCATION;

	if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE;

	remainingTries = EstEID_getRemainingTries(slotID);
	EstEID_log("EstEID_getRemainingTries(slotID) = %i", remainingTries);
	if (remainingTries == -1)
		CLOSE_SESSION_AND_RETURN(FAILURE);
	if (!remainingTries) {
		sprintf_s(EstEID_error, ESTEID_ERROR_SIZE, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED);
		CLOSE_SESSION_AND_RETURN(FAILURE);
	}
	if (remainingTries < 3) {
		sprintf_s(message, 1024, "%s %i", l10n("Tries left:"), remainingTries);
	}
	else {
		message[0] = 0;
	}

	loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pinPromptData.pin2, strlen(pinPromptData.pin2));
	if(loginResult != CKR_OK) {
		EstEID_log("loginResult = %s", pkcs11_error_message(loginResult));
		sprintf_s(EstEID_error, 1024, "C_Login error: %s (%li)", pkcs11_error_message(loginResult), loginResult);
		CLOSE_SESSION_AND_RETURN(loginResult);
	}
	
	return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, NULL);
}
コード例 #2
0
ファイル: common.c プロジェクト: mbrossard/pkcs11
CK_RV pkcs11_login_session(CK_FUNCTION_LIST_PTR funcs, FILE *out,  CK_SLOT_ID slot,
                           CK_SESSION_HANDLE_PTR session, CK_BBOOL readwrite,
                           CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pinLen)
{
    CK_SESSION_HANDLE h_session;
    CK_FLAGS flags = CKF_SERIAL_SESSION | (readwrite ? CKF_RW_SESSION : 0);
    CK_RV rc;

    rc = funcs->C_OpenSession(slot, flags, NULL, NULL, &h_session);
    if (rc != CKR_OK) {
        if(out) {
            show_error(stdout, "C_OpenSession", rc);
        }
        return rc;
    }

    if(pin) {
        rc = funcs->C_Login(h_session, user, pin, pinLen);
        if (rc != CKR_OK) {
            if(out) {
                show_error(out, "C_Login", rc);
            }
            goto end;
        }
    } else if(readwrite || pinLen > 0) {
        CK_TOKEN_INFO  info;

        rc = funcs->C_GetTokenInfo(slot, &info);
        if (rc != CKR_OK) {
            if(out) {
                show_error(out, "C_GetTokenInfo", rc);
            }
            goto end;
        }
        
        if(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
            rc = funcs->C_Login(h_session, user, NULL, 0);
            if (rc != CKR_OK) {
                if(out) {
                    show_error(out, "C_Login", rc);
                }
                goto end;
            }
        }
    }

 end:
    if (rc != CKR_OK) {
        /* We want to keep the original error code */
        CK_RV r = funcs->C_CloseSession(h_session);
        if ((r != CKR_OK) && out) {
            show_error(out, "C_CloseSession", r);
        }
    } else if(session) {
        *session = h_session;
    }
    return rc;
}
コード例 #3
0
static void test_session() {

  CK_SESSION_HANDLE session;
  CK_SESSION_INFO   info;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");

  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");

  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession2");
  asrt(funcs->C_GetSessionInfo(session, &info), CKR_OK, "GetSessionInfo");
  asrt(info.state, CKS_RW_PUBLIC_SESSION, "CHECK STATE");
  asrt(info.flags, CKF_SERIAL_SESSION | CKF_RW_SESSION, "CHECK FLAGS");
  asrt(info.ulDeviceError, 0, "CHECK DEVICE ERROR");
  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");

  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession3");
  asrt(funcs->C_CloseAllSessions(0), CKR_OK, "CloseAllSessions");

  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}
コード例 #4
0
// Connect and login to the token
int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession)
{
	char user_pin_copy[MAX_PIN_LEN+1];
	CK_RV rv;

	rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
					NULL_PTR, NULL_PTR, hSession);
	if (rv != CKR_OK)
	{
		if (rv == CKR_SLOT_ID_INVALID)
		{
			fprintf(stderr, "ERROR: The given slot does not exist.\n");
		}
		else
		{
			fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
		}
		return 1;
	}

	// Get the password
	if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
	{
		fprintf(stderr, "ERROR: Could not get user PIN\n");
		return 1;
	}

	rv = p11->C_Login(*hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
	if (rv != CKR_OK)
	{
		if (rv == CKR_PIN_INCORRECT) {
			fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
		}
		else
		{
			fprintf(stderr, "ERROR: Could not log in on the token.\n");
		}
		return 1;
	}

	return 0;
}
コード例 #5
0
static void test_login() {

  CK_SESSION_HANDLE session;
  CK_SESSION_INFO   info;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");

  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");

  asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
  asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");

  asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");
  asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");

  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");

  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}
コード例 #6
0
static CK_RV
hacky_perform_initialize_pin (GP11Slot *slot)
{
	CK_FUNCTION_LIST_PTR funcs;
	CK_SESSION_HANDLE session;
	CK_SLOT_ID slot_id;
	CK_RV rv;
	
	/* 
	 * This hack only works when:
	 *  
	 *  - Module is protected authentication path
	 *  - No other sessions are open.
	 *  
	 *  Thankfully this is the case with mate-keyring-daemon and 
	 *  the mate-keyring tool. 
	 */
	
	funcs = gp11_module_get_functions (gp11_slot_get_module (slot));
	g_return_val_if_fail (funcs, CKR_GENERAL_ERROR);
	slot_id = gp11_slot_get_handle (slot);
	
	rv = funcs->C_OpenSession (slot_id, CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session);
	if (rv != CKR_OK)
		return rv;
	
	rv = funcs->C_Login (session, CKU_SO, NULL, 0);
	if (rv == CKR_OK) {
		rv = funcs->C_InitPIN (session, NULL, 0);
		funcs->C_Logout (session);
	}
	
	funcs->C_CloseSession (session);
	
	return rv;
}
コード例 #7
0
ファイル: esteid_sign.c プロジェクト: Krabi/idkaart_public
int EstEID_signHash(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) {
	CK_SESSION_HANDLE session = 0L;
	LOG_LOCATION;

	if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE;

	char *name = EstEID_getFullNameWithPersonalCode(cert);

	for (int attempt = 0, blocked = FALSE;; attempt++) {
		char message[1024];

		int remainingTries = EstEID_getRemainingTries(slotID);
		if (remainingTries == -1)
			CLOSE_SESSION_AND_RETURN(FAILURE);
		if (!remainingTries || blocked) {
			sprintf(EstEID_error, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED);
			pinPromptData.alertFunction(pinPromptData.nativeWindowHandle, l10n("PIN2 blocked, can not sign!"));
			CLOSE_SESSION_AND_RETURN(FAILURE);
		}
		if (remainingTries < 3 || attempt) {
			sprintf(message, "%s%s %i", (attempt ? l10n("Incorrect PIN2! ") : ""), l10n("Tries left:"), remainingTries);
		}
		else {
			message[0] = 0;
		}

		int isPinPad = EstEID_isPinPad(slotID);
		CK_RV loginResult = CKR_FUNCTION_CANCELED;
		if(!isPinPad) {
			// Simple card reader
			char *pin = pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, (unsigned)atoi(EstEID_mapGet(cert, "minPinLen")), isPinPad);
			if (!pin || strlen(pin) == 0) {
				if (pin) free(pin);
				setUserCancelErrorCodeAndMessage();
				CLOSE_SESSION_AND_RETURN(FAILURE);
			}
			loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pin, strlen(pin));
			free(pin);
		}
		else {
			// PIN pad			
#ifdef _WIN32
			EstEID_log("creating pinpad dialog UI thread");
			pinpad_thread_result = -1;
			FAIL_IF_THREAD_ERROR("CreateMutex", (pinpad_thread_mutex = CreateMutex(NULL, FALSE, NULL)));
#else
			EstEID_log("creating pinpad worker thread");
			pinpad_thread_result = -1;
			FAIL_IF_PTHREAD_ERROR("pthread_mutex_init", pthread_mutex_init(&pinpad_thread_mutex, NULL));
			FAIL_IF_PTHREAD_ERROR("pthread_cond_init", pthread_cond_init(&pinpad_thread_condition, NULL));
			pthread_t pinpad_thread;
			EstEID_PINPadThreadData threadData;
			threadData.session = session;
			threadData.result = CKR_OK;
#endif
			EstEID_log("thread launched");
#ifdef _WIN32
			/*
			NB! Due to Firefox for Windows specific behaviour C_Login() is launched from main thread
			and UI code is running in separate thread if running on Windows.
			*/
			EstEID_PINPromptDataEx pinPromptDataEx;
			pinPromptDataEx.pinPromptData = pinPromptData;
			pinPromptDataEx.message = message;
			pinPromptDataEx.name = name;
			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EstEID_pinPadLogin, (LPVOID)&pinPromptDataEx, 0, NULL);
			loginResult = fl->C_Login(session, CKU_USER, NULL, 0);
			closePinPadModalSheet();
#else
			FAIL_IF_PTHREAD_ERROR("pthread_create", pthread_create(&pinpad_thread, NULL, EstEID_pinPadLogin, (void*)&threadData));
			pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, 0, isPinPad);
			loginResult = threadData.result;
#endif
			EstEID_log("pinpad sheet/dialog closed");			
			if (loginResult == CKR_FUNCTION_CANCELED) {
				setUserCancelErrorCodeAndMessage();				
				CLOSE_SESSION_AND_RETURN(FAILURE);
			}
		}
		EstEID_log("loginResult = %s", pkcs11_error_message(loginResult));
		switch (loginResult) {
			case CKR_PIN_LOCKED:
				blocked = TRUE;
			case CKR_PIN_INCORRECT:
			case CKR_PIN_INVALID:
			case CKR_PIN_LEN_RANGE:
				EstEID_log("this was attempt %i, loginResult causes to run next round", attempt);
				continue;
			default:
				if (EstEID_CK_failure("C_Login", loginResult)) CLOSE_SESSION_AND_RETURN(FAILURE);
		}
		break; // Login successful - correct PIN supplied
	}

	return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, name);
}
コード例 #8
0
ファイル: trivial.c プロジェクト: AOSC-Dev/nss-purified
int
rmain
(
  int argc,
  char *argv[]
)
{
  char *argv0 = argv[0];
  PRLibrary *lib;
  CK_C_GetFunctionList gfl;
  CK_FUNCTION_LIST_PTR epv = (CK_FUNCTION_LIST_PTR)NULL;
  CK_RV ck_rv;
  CK_INFO info;
  CK_ULONG nSlots;
  CK_SLOT_ID *pSlots;
  CK_ULONG i;
  CK_C_INITIALIZE_ARGS ia, *iap;

  (void)memset(&ia, 0, sizeof(CK_C_INITIALIZE_ARGS));
  iap = (CK_C_INITIALIZE_ARGS *)NULL;
  while( argv++, --argc ) {
    if( '-' == argv[0][0] ) {
      switch( argv[0][1] ) {
      case 'i':
        iap = &ia;
        if( ((char *)NULL != argv[1]) && ('-' != argv[1][0]) ) {
#ifdef WITH_NSS
          ia.pConfig = argv[1];
          ia.ulConfigLen = strlen(argv[1]);
          argv++, --argc;
#else
          return usage(argv0);
#endif /* WITH_NSS */
        }
        break;
      case '-':
        argv++, --argc;
        goto endargs;
      default:
        return usage(argv0);
      }
    } else {
      break;
    }
  }
 endargs:;

  if( 1 != argc ) {
    return usage(argv0);
  }

  lib = PR_LoadLibrary(argv[0]);
  if( (PRLibrary *)NULL == lib ) {
    PR_fprintf(PR_STDERR, "Can't load %s: %ld, %ld\n", argv[1], PR_GetError(), PR_GetOSError());
    return 1;
  }

  gfl = (CK_C_GetFunctionList)PR_FindSymbol(lib, "C_GetFunctionList");
  if( (CK_C_GetFunctionList)NULL == gfl ) {
    PR_fprintf(PR_STDERR, "Can't find C_GetFunctionList in %s: %ld, %ld\n", argv[1], 
               PR_GetError(), PR_GetOSError());
    return 1;
  }

  ck_rv = (*gfl)(&epv);
  if( CKR_OK != ck_rv ) {
    PR_fprintf(PR_STDERR, "CK_GetFunctionList returned 0x%08x\n", ck_rv);
    return 1;
  }

  PR_fprintf(PR_STDOUT, "Module %s loaded, epv = 0x%08x.\n\n", argv[1], (CK_ULONG)epv);

  /* C_Initialize */
  ck_rv = epv->C_Initialize(iap);
  if( CKR_OK != ck_rv ) {
    PR_fprintf(PR_STDERR, "C_Initialize returned 0x%08x\n", ck_rv);
    return 1;
  }

  /* C_GetInfo */
  (void)memset(&info, 0, sizeof(CK_INFO));
  ck_rv = epv->C_GetInfo(&info);
  if( CKR_OK != ck_rv ) {
    PR_fprintf(PR_STDERR, "C_GetInfo returned 0x%08x\n", ck_rv);
    return 1;
  }

  PR_fprintf(PR_STDOUT, "Module Info:\n");
  PR_fprintf(PR_STDOUT, "    cryptokiVersion = %lu.%02lu\n", 
             (PRUint32)info.cryptokiVersion.major, (PRUint32)info.cryptokiVersion.minor);
  PR_fprintf(PR_STDOUT, "    manufacturerID = \"%.32s\"\n", info.manufacturerID);
  PR_fprintf(PR_STDOUT, "    flags = 0x%08lx\n", info.flags);
  PR_fprintf(PR_STDOUT, "    libraryDescription = \"%.32s\"\n", info.libraryDescription);
  PR_fprintf(PR_STDOUT, "    libraryVersion = %lu.%02lu\n", 
             (PRUint32)info.libraryVersion.major, (PRUint32)info.libraryVersion.minor);
  PR_fprintf(PR_STDOUT, "\n");

  /* C_GetSlotList */
  nSlots = 0;
  ck_rv = epv->C_GetSlotList(CK_FALSE, (CK_SLOT_ID_PTR)CK_NULL_PTR, &nSlots);
  switch( ck_rv ) {
  case CKR_BUFFER_TOO_SMALL:
  case CKR_OK:
    break;
  default:
    PR_fprintf(PR_STDERR, "C_GetSlotList(FALSE, NULL, ) returned 0x%08x\n", ck_rv);
    return 1;
  }

  PR_fprintf(PR_STDOUT, "There are %lu slots.\n", nSlots);

  pSlots = (CK_SLOT_ID_PTR)PR_Calloc(nSlots, sizeof(CK_SLOT_ID));
  if( (CK_SLOT_ID_PTR)NULL == pSlots ) {
    PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", nSlots * sizeof(CK_SLOT_ID));
    return 1;
  }

  ck_rv = epv->C_GetSlotList(CK_FALSE, pSlots, &nSlots);
  if( CKR_OK != ck_rv ) {
    PR_fprintf(PR_STDERR, "C_GetSlotList(FALSE, , ) returned 0x%08x\n", ck_rv);
    return 1;
  }

  for( i = 0; i < nSlots; i++ ) {
    PR_fprintf(PR_STDOUT, "    [%lu]: CK_SLOT_ID = %lu\n", (i+1), pSlots[i]);
  }

  PR_fprintf(PR_STDOUT, "\n");

  /* C_GetSlotInfo */
  for( i = 0; i < nSlots; i++ ) {
    CK_SLOT_INFO sinfo;

    PR_fprintf(PR_STDOUT, "[%lu]: CK_SLOT_ID = %lu\n", (i+1), pSlots[i]);

    (void)memset(&sinfo, 0, sizeof(CK_SLOT_INFO));
    ck_rv = epv->C_GetSlotInfo(pSlots[i], &sinfo);
    if( CKR_OK != ck_rv ) {
      PR_fprintf(PR_STDERR, "C_GetSlotInfo(%lu, ) returned 0x%08x\n", pSlots[i], ck_rv);
      return 1;
    }

    PR_fprintf(PR_STDOUT, "    Slot Info:\n");
    PR_fprintf(PR_STDOUT, "        slotDescription = \"%.64s\"\n", sinfo.slotDescription);
    PR_fprintf(PR_STDOUT, "        manufacturerID = \"%.32s\"\n", sinfo.manufacturerID);
    PR_fprintf(PR_STDOUT, "        flags = 0x%08lx\n", sinfo.flags);
    PR_fprintf(PR_STDOUT, "            -> TOKEN PRESENT = %s\n", 
               sinfo.flags & CKF_TOKEN_PRESENT ? "TRUE" : "FALSE");
    PR_fprintf(PR_STDOUT, "            -> REMOVABLE DEVICE = %s\n",
               sinfo.flags & CKF_REMOVABLE_DEVICE ? "TRUE" : "FALSE");
    PR_fprintf(PR_STDOUT, "            -> HW SLOT = %s\n", 
               sinfo.flags & CKF_HW_SLOT ? "TRUE" : "FALSE");
    PR_fprintf(PR_STDOUT, "        hardwareVersion = %lu.%02lu\n", 
               (PRUint32)sinfo.hardwareVersion.major, (PRUint32)sinfo.hardwareVersion.minor);
    PR_fprintf(PR_STDOUT, "        firmwareVersion = %lu.%02lu\n",
               (PRUint32)sinfo.firmwareVersion.major, (PRUint32)sinfo.firmwareVersion.minor);

    if( sinfo.flags & CKF_TOKEN_PRESENT ) {
      CK_TOKEN_INFO tinfo;
      CK_MECHANISM_TYPE *pMechanismList;
      CK_ULONG nMechanisms = 0;
      CK_ULONG j;

      (void)memset(&tinfo, 0, sizeof(CK_TOKEN_INFO));
      ck_rv = epv->C_GetTokenInfo(pSlots[i], &tinfo);
      if( CKR_OK != ck_rv ) {
        PR_fprintf(PR_STDERR, "C_GetTokenInfo(%lu, ) returned 0x%08x\n", pSlots[i], ck_rv);
        return 1;
      }

      PR_fprintf(PR_STDOUT, "    Token Info:\n");
      PR_fprintf(PR_STDOUT, "        label = \"%.32s\"\n", tinfo.label);
      PR_fprintf(PR_STDOUT, "        manufacturerID = \"%.32s\"\n", tinfo.manufacturerID);
      PR_fprintf(PR_STDOUT, "        model = \"%.16s\"\n", tinfo.model);
      PR_fprintf(PR_STDOUT, "        serialNumber = \"%.16s\"\n", tinfo.serialNumber);
      PR_fprintf(PR_STDOUT, "        flags = 0x%08lx\n", tinfo.flags);
      PR_fprintf(PR_STDOUT, "            -> RNG = %s\n",
                 tinfo.flags & CKF_RNG ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> WRITE PROTECTED = %s\n",
                 tinfo.flags & CKF_WRITE_PROTECTED ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> LOGIN REQUIRED = %s\n",
                 tinfo.flags & CKF_LOGIN_REQUIRED ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> USER PIN INITIALIZED = %s\n",
                 tinfo.flags & CKF_USER_PIN_INITIALIZED ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> RESTORE KEY NOT NEEDED = %s\n",
                 tinfo.flags & CKF_RESTORE_KEY_NOT_NEEDED ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> CLOCK ON TOKEN = %s\n",
                 tinfo.flags & CKF_CLOCK_ON_TOKEN ? "TRUE" : "FALSE");
#ifdef CKF_SUPPORTS_PARALLEL
      PR_fprintf(PR_STDOUT, "            -> SUPPORTS PARALLEL = %s\n",
                 tinfo.flags & CKF_SUPPORTS_PARALLEL ? "TRUE" : "FALSE");
#endif /* CKF_SUPPORTS_PARALLEL */
      PR_fprintf(PR_STDOUT, "            -> PROTECTED AUTHENTICATION PATH = %s\n",
                 tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "            -> DUAL_CRYPTO_OPERATIONS = %s\n", 
                 tinfo.flags & CKF_DUAL_CRYPTO_OPERATIONS ? "TRUE" : "FALSE");
      PR_fprintf(PR_STDOUT, "        ulMaxSessionCount = %lu\n", tinfo.ulMaxSessionCount);
      PR_fprintf(PR_STDOUT, "        ulSessionCount = %lu\n", tinfo.ulSessionCount);
      PR_fprintf(PR_STDOUT, "        ulMaxRwSessionCount = %lu\n", tinfo.ulMaxRwSessionCount);
      PR_fprintf(PR_STDOUT, "        ulRwSessionCount = %lu\n", tinfo.ulRwSessionCount);
      PR_fprintf(PR_STDOUT, "        ulMaxPinLen = %lu\n", tinfo.ulMaxPinLen);
      PR_fprintf(PR_STDOUT, "        ulMinPinLen = %lu\n", tinfo.ulMinPinLen);
      PR_fprintf(PR_STDOUT, "        ulTotalPublicMemory = %lu\n", tinfo.ulTotalPublicMemory);
      PR_fprintf(PR_STDOUT, "        ulFreePublicMemory = %lu\n", tinfo.ulFreePublicMemory);
      PR_fprintf(PR_STDOUT, "        ulTotalPrivateMemory = %lu\n", tinfo.ulTotalPrivateMemory);
      PR_fprintf(PR_STDOUT, "        ulFreePrivateMemory = %lu\n", tinfo.ulFreePrivateMemory);
      PR_fprintf(PR_STDOUT, "        hardwareVersion = %lu.%02lu\n", 
                 (PRUint32)tinfo.hardwareVersion.major, (PRUint32)tinfo.hardwareVersion.minor);
      PR_fprintf(PR_STDOUT, "        firmwareVersion = %lu.%02lu\n",
                 (PRUint32)tinfo.firmwareVersion.major, (PRUint32)tinfo.firmwareVersion.minor);
      PR_fprintf(PR_STDOUT, "        utcTime = \"%.16s\"\n", tinfo.utcTime);


      ck_rv = epv->C_GetMechanismList(pSlots[i], (CK_MECHANISM_TYPE_PTR)CK_NULL_PTR, &nMechanisms);
      switch( ck_rv ) {
      case CKR_BUFFER_TOO_SMALL:
      case CKR_OK:
        break;
      default:
        PR_fprintf(PR_STDERR, "C_GetMechanismList(%lu, NULL, ) returned 0x%08x\n", pSlots[i], ck_rv);
        return 1;
      }

      PR_fprintf(PR_STDOUT, "    %lu mechanisms:\n", nMechanisms);

      pMechanismList = (CK_MECHANISM_TYPE_PTR)PR_Calloc(nMechanisms, sizeof(CK_MECHANISM_TYPE));
      if( (CK_MECHANISM_TYPE_PTR)NULL == pMechanismList ) {
        PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
                   nMechanisms * sizeof(CK_MECHANISM_TYPE));
        return 1;
      }

      ck_rv = epv->C_GetMechanismList(pSlots[i], pMechanismList, &nMechanisms);
      if( CKR_OK != ck_rv ) {
        PR_fprintf(PR_STDERR, "C_GetMechanismList(%lu, , ) returned 0x%08x\n", pSlots[i], ck_rv);
        return 1;
      }

      for( j = 0; j < nMechanisms; j++ ) {
        PR_fprintf(PR_STDOUT, "        {%lu}: CK_MECHANISM_TYPE = %lu\n", (j+1), pMechanismList[j]);
      }

      PR_fprintf(PR_STDOUT, "\n");

      for( j = 0; j < nMechanisms; j++ ) {
        CK_MECHANISM_INFO minfo;

        (void)memset(&minfo, 0, sizeof(CK_MECHANISM_INFO));
        ck_rv = epv->C_GetMechanismInfo(pSlots[i], pMechanismList[j], &minfo);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_GetMechanismInfo(%lu, %lu, ) returned 0x%08x\n", pSlots[i], 
                     pMechanismList[j]);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    [%lu]: CK_MECHANISM_TYPE = %lu\n", (j+1), pMechanismList[j]);
        PR_fprintf(PR_STDOUT, "    ulMinKeySize = %lu\n", minfo.ulMinKeySize);
        PR_fprintf(PR_STDOUT, "    ulMaxKeySize = %lu\n", minfo.ulMaxKeySize);
        PR_fprintf(PR_STDOUT, "    flags = 0x%08x\n", minfo.flags);
        PR_fprintf(PR_STDOUT, "        -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> SIGN_RECOVER = %s\n", minfo.flags & CKF_SIGN_RECOVER ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> VERIFY_RECOVER = %s\n", minfo.flags & CKF_VERIFY_RECOVER ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> GENERATE_KEY_PAIR = %s\n", minfo.flags & CKF_GENERATE_KEY_PAIR ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "        -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE" : "FALSE");

        PR_fprintf(PR_STDOUT, "\n");
      }

      if( tinfo.flags & CKF_LOGIN_REQUIRED ) {
        PR_fprintf(PR_STDERR, "*** LOGIN REQUIRED but not yet implemented ***\n");
        /* all the stuff about logging in as SO and setting the user pin if needed, etc. */
        return 2;
      }

      /* session to find objects */
      {
        CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
        CK_SESSION_INFO sinfo;
        CK_ATTRIBUTE_PTR pTemplate;
        CK_ULONG tnObjects = 0;

        ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);

        (void)memset(&sinfo, 0, sizeof(CK_SESSION_INFO));
        ck_rv = epv->C_GetSessionInfo(h, &sinfo);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDOUT, "C_GetSessionInfo(%lu, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    SESSION INFO:\n");
        PR_fprintf(PR_STDOUT, "        slotID = %lu\n", sinfo.slotID);
        PR_fprintf(PR_STDOUT, "        state = %lu\n", sinfo.state);
        PR_fprintf(PR_STDOUT, "        flags = 0x%08x\n", sinfo.flags);
#ifdef CKF_EXCLUSIVE_SESSION
        PR_fprintf(PR_STDOUT, "            -> EXCLUSIVE SESSION = %s\n", sinfo.flags & CKF_EXCLUSIVE_SESSION ? "TRUE" : "FALSE");
#endif /* CKF_EXCLUSIVE_SESSION */
        PR_fprintf(PR_STDOUT, "            -> RW SESSION = %s\n", sinfo.flags & CKF_RW_SESSION ? "TRUE" : "FALSE");
        PR_fprintf(PR_STDOUT, "            -> SERIAL SESSION = %s\n", sinfo.flags & CKF_SERIAL_SESSION ? "TRUE" : "FALSE");
#ifdef CKF_INSERTION_CALLBACK
        PR_fprintf(PR_STDOUT, "            -> INSERTION CALLBACK = %s\n", sinfo.flags & CKF_INSERTION_CALLBACK ? "TRUE" : "FALSE");
#endif /* CKF_INSERTION_CALLBACK */
        PR_fprintf(PR_STDOUT, "        ulDeviceError = %lu\n", sinfo.ulDeviceError);
        PR_fprintf(PR_STDOUT, "\n");

        ck_rv = epv->C_FindObjectsInit(h, (CK_ATTRIBUTE_PTR)CK_NULL_PTR, 0);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDOUT, "C_FindObjectsInit(%lu, NULL_PTR, 0) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        pTemplate = (CK_ATTRIBUTE_PTR)PR_Calloc(number_of_all_known_attribute_types, sizeof(CK_ATTRIBUTE));
        if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
          PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
                     number_of_all_known_attribute_types * sizeof(CK_ATTRIBUTE));
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    All objects:\n");

        while(1) {
          CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
          CK_ULONG nObjects = 0;
          CK_ULONG k;
          CK_ULONG nAttributes = 0;
          CK_ATTRIBUTE_PTR pT2;
          CK_ULONG l;

          ck_rv = epv->C_FindObjects(h, &o, 1, &nObjects);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_FindObjects(%lu, , 1, ) returned 0x%08x\n", h, ck_rv);
            return 1;
          }

          if( 0 == nObjects ) {
            PR_fprintf(PR_STDOUT, "\n");
            break;
          }

          tnObjects++;

          PR_fprintf(PR_STDOUT, "        OBJECT HANDLE %lu:\n", o);

          for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
            pTemplate[k].type = all_known_attribute_types[k];
            pTemplate[k].pValue = (CK_VOID_PTR)CK_NULL_PTR;
            pTemplate[k].ulValueLen = 0;
          }

          ck_rv = epv->C_GetAttributeValue(h, o, pTemplate, number_of_all_known_attribute_types);
          switch( ck_rv ) {
          case CKR_OK:
          case CKR_ATTRIBUTE_SENSITIVE:
          case CKR_ATTRIBUTE_TYPE_INVALID:
          case CKR_BUFFER_TOO_SMALL:
            break;
          default:
            PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, {all attribute types}, %lu) returned 0x%08x\n",
                       h, o, number_of_all_known_attribute_types, ck_rv);
            return 1;
          }

          for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
            if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
              nAttributes++;
            }
          }

          if( 1 ) {
            PR_fprintf(PR_STDOUT, "            %lu attributes:\n", nAttributes);
            for( k = 0; k < number_of_all_known_attribute_types; k++ ) {
              if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
                PR_fprintf(PR_STDOUT, "                0x%08x (len = %lu)\n", pTemplate[k].type, 
                           pTemplate[k].ulValueLen);
              }
            }
            PR_fprintf(PR_STDOUT, "\n");
          }

          pT2 = (CK_ATTRIBUTE_PTR)PR_Calloc(nAttributes, sizeof(CK_ATTRIBUTE));
          if( (CK_ATTRIBUTE_PTR)NULL == pT2 ) {
            PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", 
                       nAttributes * sizeof(CK_ATTRIBUTE));
            return 1;
          }

          for( l = 0, k = 0; k < number_of_all_known_attribute_types; k++ ) {
            if( -1 != (CK_LONG)pTemplate[k].ulValueLen ) {
              pT2[l].type = pTemplate[k].type;
              pT2[l].ulValueLen = pTemplate[k].ulValueLen;
              pT2[l].pValue = (CK_VOID_PTR)PR_Malloc(pT2[l].ulValueLen);
              if( (CK_VOID_PTR)NULL == pT2[l].pValue ) {
                PR_fprintf(PR_STDERR, "[memory allocation of %lu bytes failed]\n", pT2[l].ulValueLen);
                return 1;
              }
              l++;
            }
          }

          PR_ASSERT( l == nAttributes );

          ck_rv = epv->C_GetAttributeValue(h, o, pT2, nAttributes);
          switch( ck_rv ) {
          case CKR_OK:
          case CKR_ATTRIBUTE_SENSITIVE:
          case CKR_ATTRIBUTE_TYPE_INVALID:
          case CKR_BUFFER_TOO_SMALL:
            break;
          default:
            PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, {existent attribute types}, %lu) returned 0x%08x\n",
                       h, o, nAttributes, ck_rv);
            return 1;
          }

          for( l = 0; l < nAttributes; l++ ) {
            PR_fprintf(PR_STDOUT, "            type = 0x%08x, len = %ld", pT2[l].type, (CK_LONG)pT2[l].ulValueLen);
            if( -1 == (CK_LONG)pT2[l].ulValueLen ) {
              ;
            } else {
              CK_ULONG m;

              if( pT2[l].ulValueLen <= 8 ) {
                PR_fprintf(PR_STDOUT, ", value = ");
              } else {
                PR_fprintf(PR_STDOUT, ", value = \n                ");
              }

              for( m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++ ) {
                PR_fprintf(PR_STDOUT, "%02x", (CK_ULONG)(0xff & ((CK_CHAR_PTR)pT2[l].pValue)[m]));
              }

              PR_fprintf(PR_STDOUT, " ");

              for( m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++ ) {
                CK_CHAR c = ((CK_CHAR_PTR)pT2[l].pValue)[m];
                if( (c < 0x20) || (c >= 0x7f) ) {
                  c = '.';
                }
                PR_fprintf(PR_STDOUT, "%c", c);
              }
            }

            PR_fprintf(PR_STDOUT, "\n");
          }
          
          PR_fprintf(PR_STDOUT, "\n");

          for( l = 0; l < nAttributes; l++ ) {
            PR_Free(pT2[l].pValue);
          }
          PR_Free(pT2);
        } /* while(1) */

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    (%lu objects total)\n", tnObjects);

        ck_rv = epv->C_CloseSession(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CloseSession(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }
      } /* session to find objects */

      /* session to create, find, and delete a couple session objects */
      {
        CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
        CK_ATTRIBUTE one[7], two[7], three[7], delta[1], mask[1];
        CK_OBJECT_CLASS cko_data = CKO_DATA;
        CK_BBOOL false = CK_FALSE, true = CK_TRUE;
        char *key = "TEST PROGRAM";
        CK_ULONG key_len = strlen(key);
        CK_OBJECT_HANDLE hOneIn = (CK_OBJECT_HANDLE)0, hTwoIn = (CK_OBJECT_HANDLE)0, 
          hThreeIn = (CK_OBJECT_HANDLE)0, hDeltaIn = (CK_OBJECT_HANDLE)0;
        CK_OBJECT_HANDLE found[10];
        CK_ULONG nFound;

        ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);

        one[0].type = CKA_CLASS;
        one[0].pValue = &cko_data;
        one[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        one[1].type = CKA_TOKEN;
        one[1].pValue = &false;
        one[1].ulValueLen = sizeof(CK_BBOOL);
        one[2].type = CKA_PRIVATE;
        one[2].pValue = &false;
        one[2].ulValueLen = sizeof(CK_BBOOL);
        one[3].type = CKA_MODIFIABLE;
        one[3].pValue = &true;
        one[3].ulValueLen = sizeof(CK_BBOOL);
        one[4].type = CKA_LABEL;
        one[4].pValue = "Test data object one";
        one[4].ulValueLen = strlen(one[4].pValue);
        one[5].type = CKA_APPLICATION;
        one[5].pValue = key;
        one[5].ulValueLen = key_len;
        one[6].type = CKA_VALUE;
        one[6].pValue = "Object one";
        one[6].ulValueLen = strlen(one[6].pValue);

        two[0].type = CKA_CLASS;
        two[0].pValue = &cko_data;
        two[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        two[1].type = CKA_TOKEN;
        two[1].pValue = &false;
        two[1].ulValueLen = sizeof(CK_BBOOL);
        two[2].type = CKA_PRIVATE;
        two[2].pValue = &false;
        two[2].ulValueLen = sizeof(CK_BBOOL);
        two[3].type = CKA_MODIFIABLE;
        two[3].pValue = &true;
        two[3].ulValueLen = sizeof(CK_BBOOL);
        two[4].type = CKA_LABEL;
        two[4].pValue = "Test data object two";
        two[4].ulValueLen = strlen(two[4].pValue);
        two[5].type = CKA_APPLICATION;
        two[5].pValue = key;
        two[5].ulValueLen = key_len;
        two[6].type = CKA_VALUE;
        two[6].pValue = "Object two";
        two[6].ulValueLen = strlen(two[6].pValue);

        three[0].type = CKA_CLASS;
        three[0].pValue = &cko_data;
        three[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        three[1].type = CKA_TOKEN;
        three[1].pValue = &false;
        three[1].ulValueLen = sizeof(CK_BBOOL);
        three[2].type = CKA_PRIVATE;
        three[2].pValue = &false;
        three[2].ulValueLen = sizeof(CK_BBOOL);
        three[3].type = CKA_MODIFIABLE;
        three[3].pValue = &true;
        three[3].ulValueLen = sizeof(CK_BBOOL);
        three[4].type = CKA_LABEL;
        three[4].pValue = "Test data object three";
        three[4].ulValueLen = strlen(three[4].pValue);
        three[5].type = CKA_APPLICATION;
        three[5].pValue = key;
        three[5].ulValueLen = key_len;
        three[6].type = CKA_VALUE;
        three[6].pValue = "Object three";
        three[6].ulValueLen = strlen(three[6].pValue);

        ck_rv = epv->C_CreateObject(h, one, 7, &hOneIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, one, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object one: handle = %lu\n", hOneIn);

        ck_rv = epv->C_CreateObject(h, two, 7, &hTwoIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, two, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object two: handle = %lu\n", hTwoIn);

        ck_rv = epv->C_CreateObject(h, three, 7, &hThreeIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, three, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object three: handle = %lu\n", hThreeIn);

        delta[0].type = CKA_VALUE;
        delta[0].pValue = "Copied object";
        delta[0].ulValueLen = strlen(delta[0].pValue);

        ck_rv = epv->C_CopyObject(h, hThreeIn, delta, 1, &hDeltaIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CopyObject(%lu, %lu, delta, 1, ) returned 0x%08x\n", 
                     h, hThreeIn, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Copied object three: new handle = %lu\n", hDeltaIn);

        mask[0].type = CKA_APPLICATION;
        mask[0].pValue = key;
        mask[0].ulValueLen = key_len;

        ck_rv = epv->C_FindObjectsInit(h, mask, 1);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        (void)memset(&found, 0, sizeof(found));
        nFound = 0;
        ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        if( 4 != nFound ) {
          PR_fprintf(PR_STDERR, "Found %lu objects, not 4.\n", nFound);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Found 4 objects: %lu, %lu, %lu, %lu\n", 
                   found[0], found[1], found[2], found[3]);

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        ck_rv = epv->C_DestroyObject(h, hThreeIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, hThreeIn, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Destroyed object three (handle = %lu)\n", hThreeIn);

        delta[0].type = CKA_APPLICATION;
        delta[0].pValue = "Changed application";
        delta[0].ulValueLen = strlen(delta[0].pValue);

        ck_rv = epv->C_SetAttributeValue(h, hTwoIn, delta, 1);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
                     h, hTwoIn, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Changed object two (handle = %lu).\n", hTwoIn);

        /* Can another session find these session objects? */
        {
          CK_SESSION_HANDLE h2 = (CK_SESSION_HANDLE)0;

          ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h2);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
            return 1;
          }

          PR_fprintf(PR_STDOUT, "    Opened a second session: handle = 0x%08x\n", h2);

          /* mask is still the same */

          ck_rv = epv->C_FindObjectsInit(h2, mask, 1);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
                       h2, ck_rv);
            return 1;
          }

          (void)memset(&found, 0, sizeof(found));
          nFound = 0;
          ck_rv = epv->C_FindObjects(h2, found, 10, &nFound);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
                       h2, ck_rv);
            return 1;
          }

          if( 2 != nFound ) {
            PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
            return 1;
          }

          PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
                     found[0], found[1]);

          ck_rv = epv->C_FindObjectsFinal(h2);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h2, ck_rv);
            return 1;
          }

          /* Leave the session hanging open, we'll CloseAllSessions later */
        } /* Can another session find these session objects? */

        ck_rv = epv->C_CloseAllSessions(pSlots[i]);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CloseAllSessions(%lu) returned 0x%08x\n", pSlots[i], ck_rv);
          return 1;
        }
      } /* session to create, find, and delete a couple session objects */

      /* Might be interesting to do a find here to verify that all session objects are gone. */

      if( tinfo.flags & CKF_WRITE_PROTECTED ) {
        PR_fprintf(PR_STDOUT, "Token is write protected, skipping token-object tests.\n");
      } else {
        CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
        CK_ATTRIBUTE tobj[7], tsobj[7], stobj[7], delta[1], mask[2];
        CK_OBJECT_CLASS cko_data = CKO_DATA;
        CK_BBOOL false = CK_FALSE, true = CK_TRUE;
        char *key = "TEST PROGRAM";
        CK_ULONG key_len = strlen(key);
        CK_OBJECT_HANDLE hTIn = (CK_OBJECT_HANDLE)0, hTSIn = (CK_OBJECT_HANDLE)0, 
          hSTIn = (CK_OBJECT_HANDLE)0, hDeltaIn = (CK_OBJECT_HANDLE)0;
        CK_OBJECT_HANDLE found[10];
        CK_ULONG nFound;

        ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);

        tobj[0].type = CKA_CLASS;
        tobj[0].pValue = &cko_data;
        tobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        tobj[1].type = CKA_TOKEN;
        tobj[1].pValue = &true;
        tobj[1].ulValueLen = sizeof(CK_BBOOL);
        tobj[2].type = CKA_PRIVATE;
        tobj[2].pValue = &false;
        tobj[2].ulValueLen = sizeof(CK_BBOOL);
        tobj[3].type = CKA_MODIFIABLE;
        tobj[3].pValue = &true;
        tobj[3].ulValueLen = sizeof(CK_BBOOL);
        tobj[4].type = CKA_LABEL;
        tobj[4].pValue = "Test data object token";
        tobj[4].ulValueLen = strlen(tobj[4].pValue);
        tobj[5].type = CKA_APPLICATION;
        tobj[5].pValue = key;
        tobj[5].ulValueLen = key_len;
        tobj[6].type = CKA_VALUE;
        tobj[6].pValue = "Object token";
        tobj[6].ulValueLen = strlen(tobj[6].pValue);

        tsobj[0].type = CKA_CLASS;
        tsobj[0].pValue = &cko_data;
        tsobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        tsobj[1].type = CKA_TOKEN;
        tsobj[1].pValue = &true;
        tsobj[1].ulValueLen = sizeof(CK_BBOOL);
        tsobj[2].type = CKA_PRIVATE;
        tsobj[2].pValue = &false;
        tsobj[2].ulValueLen = sizeof(CK_BBOOL);
        tsobj[3].type = CKA_MODIFIABLE;
        tsobj[3].pValue = &true;
        tsobj[3].ulValueLen = sizeof(CK_BBOOL);
        tsobj[4].type = CKA_LABEL;
        tsobj[4].pValue = "Test data object token->session";
        tsobj[4].ulValueLen = strlen(tsobj[4].pValue);
        tsobj[5].type = CKA_APPLICATION;
        tsobj[5].pValue = key;
        tsobj[5].ulValueLen = key_len;
        tsobj[6].type = CKA_VALUE;
        tsobj[6].pValue = "Object token->session";
        tsobj[6].ulValueLen = strlen(tsobj[6].pValue);

        stobj[0].type = CKA_CLASS;
        stobj[0].pValue = &cko_data;
        stobj[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        stobj[1].type = CKA_TOKEN;
        stobj[1].pValue = &false;
        stobj[1].ulValueLen = sizeof(CK_BBOOL);
        stobj[2].type = CKA_PRIVATE;
        stobj[2].pValue = &false;
        stobj[2].ulValueLen = sizeof(CK_BBOOL);
        stobj[3].type = CKA_MODIFIABLE;
        stobj[3].pValue = &true;
        stobj[3].ulValueLen = sizeof(CK_BBOOL);
        stobj[4].type = CKA_LABEL;
        stobj[4].pValue = "Test data object session->token";
        stobj[4].ulValueLen = strlen(stobj[4].pValue);
        stobj[5].type = CKA_APPLICATION;
        stobj[5].pValue = key;
        stobj[5].ulValueLen = key_len;
        stobj[6].type = CKA_VALUE;
        stobj[6].pValue = "Object session->token";
        stobj[6].ulValueLen = strlen(stobj[6].pValue);

        ck_rv = epv->C_CreateObject(h, tobj, 7, &hTIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object token: handle = %lu\n", hTIn);

        ck_rv = epv->C_CreateObject(h, tsobj, 7, &hTSIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object token->session: handle = %lu\n", hTSIn);
        ck_rv = epv->C_CreateObject(h, stobj, 7, &hSTIn);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created object session->token: handle = %lu\n", hSTIn);

        /* I've created two token objects and one session object; find the two */

        mask[0].type = CKA_APPLICATION;
        mask[0].pValue = key;
        mask[0].ulValueLen = key_len;
        mask[1].type = CKA_TOKEN;
        mask[1].pValue = &true;
        mask[1].ulValueLen = sizeof(CK_BBOOL);

        ck_rv = epv->C_FindObjectsInit(h, mask, 2);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        (void)memset(&found, 0, sizeof(found));
        nFound = 0;
        ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        if( 2 != nFound ) {
          PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
                   found[0], found[1]);

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        /* Convert a token to session object */

        delta[0].type = CKA_TOKEN;
        delta[0].pValue = &false;
        delta[0].ulValueLen = sizeof(CK_BBOOL);

        ck_rv = epv->C_SetAttributeValue(h, hTSIn, delta, 1);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
                     h, hTSIn, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Changed object from token to session (handle = %lu).\n", hTSIn);

        /* Now find again; there should be one */

        mask[0].type = CKA_APPLICATION;
        mask[0].pValue = key;
        mask[0].ulValueLen = key_len;
        mask[1].type = CKA_TOKEN;
        mask[1].pValue = &true;
        mask[1].ulValueLen = sizeof(CK_BBOOL);

        ck_rv = epv->C_FindObjectsInit(h, mask, 2);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        (void)memset(&found, 0, sizeof(found));
        nFound = 0;
        ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        if( 1 != nFound ) {
          PR_fprintf(PR_STDERR, "Found %lu objects, not 1.\n", nFound);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Found 1 objects: %lu\n", 
                   found[0]);

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        /* Convert a session to a token object */

        delta[0].type = CKA_TOKEN;
        delta[0].pValue = &true;
        delta[0].ulValueLen = sizeof(CK_BBOOL);

        ck_rv = epv->C_SetAttributeValue(h, hSTIn, delta, 1);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_SetAttributeValue(%lu, %lu, delta, 1) returned 0x%08x\n", 
                     h, hSTIn, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Changed object from session to token (handle = %lu).\n", hSTIn);

        /* Now find again; there should be two again */

        mask[0].type = CKA_APPLICATION;
        mask[0].pValue = key;
        mask[0].ulValueLen = key_len;
        mask[1].type = CKA_TOKEN;
        mask[1].pValue = &true;
        mask[1].ulValueLen = sizeof(CK_BBOOL);

        ck_rv = epv->C_FindObjectsInit(h, mask, 2);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 2) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        (void)memset(&found, 0, sizeof(found));
        nFound = 0;
        ck_rv = epv->C_FindObjects(h, found, 10, &nFound);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjects(%lu,, 10, ) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        if( 2 != nFound ) {
          PR_fprintf(PR_STDERR, "Found %lu objects, not 2.\n", nFound);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Found 2 objects: %lu, %lu\n", 
                   found[0], found[1]);

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        /* Delete the two (found) token objects to clean up */

        ck_rv = epv->C_DestroyObject(h, found[0]);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, found[0], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Destroyed token object (handle = %lu)\n", found[0]);

        ck_rv = epv->C_DestroyObject(h, found[1]);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_DestroyObject(%lu, %lu) returned 0x%08x\n", h, found[1], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Destroyed token object (handle = %lu)\n", found[1]);
        
        /* Close the session and all objects should be gone */

        ck_rv = epv->C_CloseSession(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CloseSession(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }
      } /* if( tinfo.flags & CKF_WRITE_PROTECTED ) */

      if( tinfo.flags & CKF_WRITE_PROTECTED ) {
        PR_fprintf(PR_STDOUT, "Token is write protected, skipping leaving a record.\n");
      } else {
        CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
        CK_ATTRIBUTE record[7], mask[2];
        CK_OBJECT_CLASS cko_data = CKO_DATA;
        CK_BBOOL false = CK_FALSE, true = CK_TRUE;
        char *key = "TEST RECORD";
        CK_ULONG key_len = strlen(key);
        CK_OBJECT_HANDLE hin = (CK_OBJECT_HANDLE)0;
        char timebuffer[256];

        ck_rv = epv->C_OpenSession(pSlots[i], CKF_SERIAL_SESSION, (CK_VOID_PTR)CK_NULL_PTR, (CK_NOTIFY)CK_NULL_PTR, &h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_OpenSession(%lu, CKF_SERIAL_SESSION, , ) returned 0x%08x\n", pSlots[i], ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Opened a session: handle = 0x%08x\n", h);

        /* I can't believe how hard NSPR makes this operation */
        {
          time_t now = 0;
          struct tm *tm;
          time(&now);
          tm = localtime(&now);
          strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %T %Z", tm);
        }

        record[0].type = CKA_CLASS;
        record[0].pValue = &cko_data;
        record[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        record[1].type = CKA_TOKEN;
        record[1].pValue = &true;
        record[1].ulValueLen = sizeof(CK_BBOOL);
        record[2].type = CKA_PRIVATE;
        record[2].pValue = &false;
        record[2].ulValueLen = sizeof(CK_BBOOL);
        record[3].type = CKA_MODIFIABLE;
        record[3].pValue = &true;
        record[3].ulValueLen = sizeof(CK_BBOOL);
        record[4].type = CKA_LABEL;
        record[4].pValue = "Test record";
        record[4].ulValueLen = strlen(record[4].pValue);
        record[5].type = CKA_APPLICATION;
        record[5].pValue = key;
        record[5].ulValueLen = key_len;
        record[6].type = CKA_VALUE;
        record[6].pValue = timebuffer;
        record[6].ulValueLen = strlen(timebuffer)+1;

        PR_fprintf(PR_STDOUT, "    Timestamping with \"%s\"\n", timebuffer);

        ck_rv = epv->C_CreateObject(h, record, 7, &hin);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_CreateObject(%lu, tobj, 7, ) returned 0x%08x\n", h, ck_rv);
          return 1;
        }

        PR_fprintf(PR_STDOUT, "    Created record object: handle = %lu\n", hin);
        
        PR_fprintf(PR_STDOUT, "   == All test timestamps ==\n");

        mask[0].type = CKA_CLASS;
        mask[0].pValue = &cko_data;
        mask[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
        mask[1].type = CKA_APPLICATION;
        mask[1].pValue = key;
        mask[1].ulValueLen = key_len;

        ck_rv = epv->C_FindObjectsInit(h, mask, 2);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsInit(%lu, mask, 1) returned 0x%08x\n", 
                     h, ck_rv);
          return 1;
        }

        while( 1 ) {
          CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
          CK_ULONG nObjects = 0;
          CK_ATTRIBUTE value[1];
          char buffer[1024];

          ck_rv = epv->C_FindObjects(h, &o, 1, &nObjects);
          if( CKR_OK != ck_rv ) {
            PR_fprintf(PR_STDERR, "C_FindObjects(%lu, , 1, ) returned 0x%08x\n", h, ck_rv);
            return 1;
          }

          if( 0 == nObjects ) {
            PR_fprintf(PR_STDOUT, "\n");
            break;
          }

          value[0].type = CKA_VALUE;
          value[0].pValue = buffer;
          value[0].ulValueLen = sizeof(buffer);

          ck_rv = epv->C_GetAttributeValue(h, o, value, 1);
          switch( ck_rv ) {
          case CKR_OK:
            PR_fprintf(PR_STDOUT, "    %s\n", value[0].pValue);
            break;
          case CKR_ATTRIBUTE_SENSITIVE:
            PR_fprintf(PR_STDOUT, "    [Sensitive???]\n");
            break;
          case CKR_ATTRIBUTE_TYPE_INVALID:
            PR_fprintf(PR_STDOUT, "    [Invalid attribute???]\n");
            break;
          case CKR_BUFFER_TOO_SMALL:
            PR_fprintf(PR_STDOUT, "    (result > 1k (%lu))\n", value[0].ulValueLen);
            break;
          default:
            PR_fprintf(PR_STDERR, "C_GetAtributeValue(%lu, %lu, CKA_VALUE, 1) returned 0x%08x\n",
                       h, o);
            return 1;
          }
        } /* while */

        ck_rv = epv->C_FindObjectsFinal(h);
        if( CKR_OK != ck_rv ) {
          PR_fprintf(PR_STDERR, "C_FindObjectsFinal(%lu) returned 0x%08x\n", h, ck_rv);
          return 1;
        }
      } /* "leaving a record" else clause */

    }

    PR_fprintf(PR_STDOUT, "\n");
  }

  return 0;
}
コード例 #9
0
ファイル: main.cpp プロジェクト: ggonzalez/Man-In-Remote
void
processRequest(int client)
{
	DataMarshalling	*d = NULL;

	while (1) {
		d = new DataMarshalling(client);
		d->recvData();
		if (!strcmp(d->getMsgType(), "C_Initialize")) {
			int	p = 0;
			printf("Processing: C_Initialize\n");
			p = d->unpackInt();
			if (p == 0)
				pFunctionList->C_Initialize(NULL);
			else {
				printf("ERROR: C_Initialize shouldn't be called with not NULL\n");
			}
		} else if (!strcmp(d->getMsgType(), "C_Finalize")) {
			int		p = 0;
			CK_RV	ret = 0;

			printf("Processing: C_Finalize\n");
			p = d->unpackInt();
			if (p == NULL) {
				ret = pFunctionList->C_Finalize(NULL);
			} else {
				printf("ERROR: C_Finalize shouldn't be called with not NULL\n");
				ret = CKR_CANCEL;
			}
			{
				CK_ULONG		count = 0;
				
				DataMarshalling	*d2 = new DataMarshalling(client);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
			break;
		} else if (!strcmp(d->getMsgType(), "C_GetSlotList")) {
			int	p = 0;
			printf("Processing: C_GetSlotList\n");
			p = d->unpackInt();
			if (p == 0) {
				CK_ULONG		count = 0;
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Retrieving Slots size
				 */
				ret = pFunctionList->C_GetSlotList(TRUE, NULL, &count);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&count);
				d2->sendData();
				delete d2;
			} else {
				CK_ULONG		count = 0;
				CK_SLOT_ID_PTR	slot = NULL;
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Retrieving Slots size
				 */
				pFunctionList->C_GetSlotList(TRUE, NULL, &count);
				slot = new(CK_SLOT_ID[count]);

				ret = pFunctionList->C_GetSlotList(TRUE, slot, &count);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&count);
				for (int i = 0; i < count; i ++)
					d2->packInt((char *)&slot[i]);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_OpenSession")) {
			unsigned int	slotId = 0, flags = 0;
			CK_SESSION_HANDLE	sessionId = 0;
			printf("Processing: C_OpenSession\n");
			slotId = d->unpackInt();
			flags = d->unpackInt();
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_OpenSession(slotId, flags, NULL, NULL, &sessionId);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&sessionId);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_CloseSession")) {
			CK_SESSION_HANDLE	sessionId = 0;
			printf("Processing: C_CloseSession\n");
			sessionId = d->unpackInt();
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_CloseSession(sessionId);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetInfo")) {
			unsigned int	slotId = 0, flags = 0;
			CK_SESSION_HANDLE	sessionId = 0;
			CK_INFO		info;
			printf("Processing: C_GetInfo\n");
			slotId = d->unpackInt();
			{
				CK_RV			ret = 0;
				CK_TOKEN_INFO	token;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_GetInfo(&info);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packChar(info.cryptokiVersion.major);
				d2->packChar(info.cryptokiVersion.minor);
				d2->packMem((char *)info.manufacturerID, 32);
				d2->packInt((char *)&info.flags);
				d2->packMem((char *)info.libraryDescription, 32);
				d2->packChar(info.libraryVersion.major);
				d2->packChar(info.libraryVersion.minor);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetSlotInfo")) {
			unsigned int	slotId = 0, flags = 0;
			CK_SESSION_HANDLE	sessionId = 0;
			printf("Processing: C_GetSlotInfo\n");
			slotId = d->unpackInt();
			{
				CK_RV			ret = 0;
				CK_SLOT_INFO	slot;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_GetSlotInfo(slotId, &slot);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packMem((char *)slot.slotDescription, 64);
				d2->packMem((char *)slot.manufacturerID, 32);
				d2->packInt((char *)&slot.flags);
				d2->packChar(slot.hardwareVersion.major);
				d2->packChar(slot.hardwareVersion.minor);
				d2->packChar(slot.firmwareVersion.major);
				d2->packChar(slot.firmwareVersion.minor);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetTokenInfo")) {
			unsigned int	slotId = 0, flags = 0;
			CK_SESSION_HANDLE	sessionId = 0;
			printf("Processing: C_GetTokenInfo\n");
			slotId = d->unpackInt();
			{
				CK_RV			ret = 0;
				CK_TOKEN_INFO	token;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_GetTokenInfo(slotId, &token);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packMem((char *)token.label, 32);
				d2->packMem((char *)token.manufacturerID, 32);
				d2->packMem((char *)token.model, 16);
				d2->packMem((char *)token.serialNumber, 16);
				d2->packInt((char *)&token.flags);
				d2->packInt((char *)&token.ulMaxSessionCount);
				d2->packInt((char *)&token.ulSessionCount);
				d2->packInt((char *)&token.ulMaxRwSessionCount);
				d2->packInt((char *)&token.ulRwSessionCount);
				d2->packInt((char *)&token.ulMaxPinLen);
				d2->packInt((char *)&token.ulMinPinLen);
				d2->packInt((char *)&token.ulTotalPublicMemory);
				d2->packInt((char *)&token.ulFreePublicMemory);
				d2->packInt((char *)&token.ulTotalPrivateMemory);
				d2->packInt((char *)&token.ulFreePrivateMemory);
				d2->packChar(token.hardwareVersion.major);
				d2->packChar(token.hardwareVersion.minor);
				d2->packChar(token.firmwareVersion.major);
				d2->packChar(token.firmwareVersion.minor);
				d2->packMem((char *)token.utcTime, 16);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetMechanismList")) {
			unsigned int	slotId = 0;
			CK_MECHANISM_TYPE_PTR	pMechanismList = NULL;
			printf("Processing: C_GetMechanismList\n");
			slotId = d->unpackInt();
			pMechanismList = (CK_MECHANISM_TYPE_PTR)d->unpackInt();
			if (pMechanismList == NULL) {
				CK_ULONG		count = 0;
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Retrieving Slots size
				 */
				ret = pFunctionList->C_GetMechanismList(slotId, pMechanismList, &count);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&count);
				printf("C_GetMechanismList count: %d\n", count);
				d2->sendData();
				delete d2;
			} else {
				CK_ULONG		count = 0;
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Retrieving Slots size
				 */
				pFunctionList->C_GetMechanismList(TRUE, NULL, &count);
				pMechanismList = new(CK_MECHANISM_TYPE[count]);

				ret = pFunctionList->C_GetMechanismList(slotId, pMechanismList, &count);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&count);
				printf("C_GetMechanismList count: %d\n", count);
				for (int i = 0; i < count; i ++)
					d2->packInt((char *)&pMechanismList[i]);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetMechanismInfo")) {
			unsigned int	slotId = 0, mechanismType = 0;
			printf("Processing: C_GetMechanismInfo\n");
			slotId = d->unpackInt();
			mechanismType = d->unpackInt();
			{
				CK_RV				ret = 0;
				CK_MECHANISM_INFO	mechanism;
				DataMarshalling	*d2 = new DataMarshalling(client);

				ret = pFunctionList->C_GetMechanismInfo(slotId, mechanismType, &mechanism);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&mechanism.ulMinKeySize);
				d2->packInt((char *)&mechanism.ulMaxKeySize);
				d2->packInt((char *)&mechanism.flags);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_Login")) {
			CK_SESSION_HANDLE	sessionId = 0;
			unsigned int		user = 0, len = 0;
			CK_CHAR_PTR			pin = NULL;

			printf("Processing: C_Login\n");

			sessionId = d->unpackInt();
			user = d->unpackInt();
			len = d->unpackInt();
			pin = (CK_CHAR_PTR) calloc(1, len + 1);
			if (!pin) {
				printf("ERROR: NO MEMORY\n");
				break;
			}
			d->unpackMem((char *)pin, len);
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_Login(sessionId, user, pin, len);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_Logout")) {
			CK_SESSION_HANDLE	sessionId = 0;

			printf("Processing: C_Logout\n");

			sessionId = d->unpackInt();
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_Logout(sessionId);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_FindObjectsInit")) {
			CK_SESSION_HANDLE	sessionId = 0;
			unsigned int		len = 0;
			CK_ATTRIBUTE_PTR	attr = NULL;

			printf("Processing: C_FindObjectsInit\n");

			sessionId = d->unpackInt();
			len = d->unpackInt();
			attr = (CK_ATTRIBUTE_PTR) calloc(len, sizeof(CK_ATTRIBUTE));
			if (!attr) {
				printf("ERROR: NO MEMORY\n");
				break;
			}
			for (int i = 0; i < len; i ++) {
				attr[i].type = d->unpackInt();
				attr[i].ulValueLen = d->unpackInt();
				attr[i].pValue = (char *)calloc(1, attr[i].ulValueLen);
				d->unpackMem((char *)attr[i].pValue, attr[i].ulValueLen);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_FindObjectsInit(sessionId, attr, len);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_FindObjects")) {
			CK_SESSION_HANDLE	sessionId = 0;
			CK_OBJECT_HANDLE_PTR	phObject = NULL;
			CK_ULONG			len = 0, maxlen = 0;

			printf("Processing: C_FindObjects\n");

			sessionId = d->unpackInt();
			maxlen = d->unpackInt();
			if (maxlen > 0) {
				phObject = new(CK_OBJECT_HANDLE[maxlen]);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_FindObjects(sessionId, phObject, maxlen, &len);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&len);
				for (int i = 0; i < len && i < maxlen; i ++)
					d2->packInt((char *)&phObject[i]);
				
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetAttributeValue")) {
			CK_SESSION_HANDLE	sessionId = 0;
			CK_OBJECT_HANDLE	hObject = 0;
			CK_ULONG			len = 0;
			CK_ATTRIBUTE_PTR	attr = NULL;

			printf("Processing: C_GetAttributeValue\n");

			sessionId = d->unpackInt();
			hObject = d->unpackInt();
			len = d->unpackInt();
			attr = (CK_ATTRIBUTE_PTR) calloc(len, sizeof(CK_ATTRIBUTE));
			if (!attr) {
				printf("ERROR: NO MEM C_GetAttributeValue\n");
				break;
			}
			for (int i = 0; i < len; i ++) {
				attr[i].type = d->unpackInt();
				attr[i].ulValueLen = d->unpackInt();
				attr[i].pValue = (char *)d->unpackInt();
				if (attr[i].pValue != NULL) {
					attr[i].pValue = (char *)calloc(1, attr[i].ulValueLen);
					if (!attr[i].pValue) {
						printf("ERROR: NO MEM\n");
						exit(-1);
					}
					//d->unpackMem((char *)attr[i].pValue, attr[i].ulValueLen);
				}
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);

				ret = pFunctionList->C_GetAttributeValue(sessionId, hObject, attr, len);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				for (int i = 0; i < len; i ++) {
					d2->packInt((char *)&attr[i].type);
					d2->packInt((char *)&attr[i].ulValueLen);
					d2->packInt((char *)&attr[i].pValue);
					if (attr[i].pValue != NULL) {
						d2->packMem((char *)attr[i].pValue, attr[i].ulValueLen);
#ifdef FUNC_DEBUG_
						if (i == 2) {
							PCCERT_CONTEXT	pCertContext;

							pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,((BYTE *)attr[i].pValue),attr[i].ulValueLen);
							printf("data len: %d\n", attr[i].ulValueLen);
							printf("issuer len: %d\n", pCertContext->pCertInfo->Issuer.cbData);
							std::wcout << byte2str(pCertContext->pCertInfo->Issuer.pbData, pCertContext->pCertInfo->Issuer.cbData);
							CertFreeCertificateContext(pCertContext);
						}
		
#endif
					}
				}
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_FindObjectsFinal")) {
			CK_SESSION_HANDLE	sessionId = 0;

			printf("Processing: C_FindObjectsFinal\n");

			sessionId = d->unpackInt();
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_FindObjectsFinal(sessionId);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_SignInit")) {
			CK_SESSION_HANDLE	sessionId = 0;
			CK_MECHANISM		mechanism;
			CK_OBJECT_HANDLE	hKey;

			printf("Processing: C_SignInit\n");

			sessionId = d->unpackInt();
			hKey = d->unpackInt();
			mechanism.mechanism = d->unpackInt();
			mechanism.ulParameterLen = d->unpackInt();
			mechanism.pParameter = NULL;
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_SignInit(sessionId, &mechanism, hKey);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_Sign")) {
			CK_SESSION_HANDLE	sessionId = 0;
			char				*data = NULL, *signature = NULL;
			CK_ULONG			dataLen = 0, signatureLen = 0;

			printf("Processing: C_Sign\n");

			sessionId = d->unpackInt();
			dataLen = d->unpackInt();
			data = (char *)d->unpackInt();
			if (data != NULL) {
				data = (char *)calloc(1, dataLen);
				if (!data) {
					printf("ERROR: NO MEM C_Sign\n");
					break;
				}
				d->unpackMem((char *)data, dataLen);
			}
			signatureLen = d->unpackInt();
			signature = (char *)d->unpackInt();
			if (signature != NULL) {
				signature = (char *)calloc(1, signatureLen);
				if (!signature) {
					printf("ERROR: NO MEM C_Sign\n");
					break;
				}
				d->unpackMem((char *)signature, signatureLen);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_Sign(sessionId, (CK_BYTE_PTR)data, dataLen, (CK_BYTE_PTR)signature, &signatureLen);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&signatureLen);
				if (signature != NULL)
					d2->packMem((char *)signature, signatureLen);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_VerifyInit")) {
			CK_SESSION_HANDLE	sessionId = 0;
			CK_MECHANISM		mechanism;
			CK_OBJECT_HANDLE	hKey;

			printf("Processing: C_VerifyInit\n");

			sessionId = d->unpackInt();
			hKey = d->unpackInt();
			mechanism.mechanism = d->unpackInt();
			mechanism.ulParameterLen = d->unpackInt();
			mechanism.pParameter = NULL;
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_VerifyInit(sessionId, &mechanism, hKey);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_Verify")) {
			CK_SESSION_HANDLE	sessionId = 0;
			char				*data = NULL, *signature = NULL;
			CK_ULONG			dataLen = 0, signatureLen = 0;

			printf("Processing: C_Verify\n");

			sessionId = d->unpackInt();
			dataLen = d->unpackInt();
			data = (char *)d->unpackInt();
			if (data != NULL) {
				data = (char *)calloc(1, dataLen);
				if (!data) {
					printf("ERROR: NO MEM C_Verify\n");
					break;
				}
				d->unpackMem((char *)data, dataLen);
			}
			signatureLen = d->unpackInt();
			signature = (char *)d->unpackInt();
			if (signature != NULL) {
				signature = (char *)calloc(1, signatureLen);
				if (!signature) {
					printf("ERROR: NO MEM C_Verify\n");
					break;
				}
				d->unpackMem((char *)signature, signatureLen);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_Verify(sessionId, (CK_BYTE_PTR)data, dataLen, (CK_BYTE_PTR)signature, signatureLen);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GenerateRandom")) {
			CK_SESSION_HANDLE	sessionId = 0;
			char				*data = NULL;
			CK_ULONG			dataLen = 0;

			printf("Processing: C_GenerateRandom\n");

			sessionId = d->unpackInt();
			dataLen = d->unpackInt();
			data = (char *)d->unpackInt();
			if (data != NULL) {
				data = (char *)calloc(1, dataLen);
				if (!data) {
					printf("ERROR: NO MEM C_GenerateRandom\n");
					break;
				}
				//d->unpackMem((char *)data, dataLen);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_GenerateRandom(sessionId, (CK_BYTE_PTR)data, dataLen);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				if (data != NULL)
					d2->packMem((char *)data, dataLen);
				d2->sendData();
				delete d2;
			}
		}  else if (!strcmp(d->getMsgType(), "C_SeedRandom")) {
			CK_SESSION_HANDLE	sessionId = 0;
			char				*data = NULL;
			CK_ULONG			dataLen = 0;

			printf("Processing: C_SeedRandom\n");

			sessionId = d->unpackInt();
			dataLen = d->unpackInt();
			data = (char *)d->unpackInt();
			if (data != NULL) {
				data = (char *)calloc(1, dataLen);
				if (!data) {
					printf("ERROR: NO MEM C_SeedRandom\n");
					break;
				}
				d->unpackMem((char *)data, dataLen);
			}
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_SeedRandom(sessionId, (CK_BYTE_PTR)data, dataLen);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_GetSessionInfo")) {
			CK_SESSION_HANDLE	sessionId = 0;

			printf("Processing: C_GetSessionInfo\n");
			sessionId = d->unpackInt();
			{
				CK_RV			ret = 0;
				CK_SESSION_INFO	info;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_GetSessionInfo(sessionId, &info);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->packInt((char *)&info.slotID);
				d2->packInt((char *)&info.state);
				d2->packInt((char *)&info.flags);
				d2->packInt((char *)&info.ulDeviceError);
				d2->sendData();
				delete d2;
			}
		} else if (!strcmp(d->getMsgType(), "C_CloseAllSessions")) {
			CK_SLOT_ID	slotID = 0;

			printf("Processing: C_Logout\n");

			slotID = d->unpackInt();
			{
				CK_RV			ret = 0;
				DataMarshalling	*d2 = new DataMarshalling(client);
				/*
				 * Opening session
				 */
				ret = pFunctionList->C_CloseAllSessions(slotID);
				d2->setMsgType(d->getMsgType());
				d2->packInt((char *)&ret);
				d2->sendData();
				delete d2;
			}
		} else {
			pFunctionList->C_Finalize(NULL);
		}
		delete d;
	}
}
コード例 #10
0
ファイル: esteid_sign.c プロジェクト: Krabi/idkaart_public
int EstEID_signHash(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) {
	CK_SESSION_HANDLE session = 0L;

	if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE;

	const char *givenName = EstEID_mapGet(cert, "givenName");
	if (!givenName) givenName = "";
	const char *surname = EstEID_mapGet(cert, "surname");
	if (!surname) surname = "";
	const char *personalID = EstEID_mapGet(cert, "serialNumber");
	if (!personalID) personalID = "";

	char *name = (char *)malloc(strlen(givenName) + strlen(surname) + strlen(personalID) + 4);
	sprintf(name, "%s %s", givenName, surname);
	if(strlen(personalID)) {
		strcat(name, ", ");
		strcat(name, personalID);
	}

	for (int attempt = 0, blocked = FALSE;; attempt++) {
		char message[1024];

		int remainingTries = EstEID_getRemainingTries(slotID);
		if (remainingTries == -1)
			CLOSE_SESSION_AND_FAIL;
		if (!remainingTries || blocked) {
			sprintf(EstEID_error, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED);
			pinPromptData.alertFunction(pinPromptData.nativeWindowHandle, l10n("PIN2 blocked, cannot sign!"));
			CLOSE_SESSION_AND_FAIL;
		}
		if (remainingTries < 3 || attempt) {
			sprintf(message, "%s%s %i", (attempt ? l10n("Incorrect PIN2! ") : ""), l10n("Tries left:"), remainingTries);
		}
		else {
			message[0] = 0;
		}

		int isPinPad = EstEID_isPinPad(slotID);
		CK_RV loginResult = CKR_FUNCTION_CANCELED;
		if(!isPinPad) {
			// Simple card reader
			char *pin = pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, (unsigned)atoi(EstEID_mapGet(cert, "minPinLen")), isPinPad);
			if (!pin || strlen(pin) == 0) {
				if (pin) free(pin);
				setUserCancelErrorCodeAndMessage();
				CLOSE_SESSION_AND_FAIL;
			}
			loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pin, strlen(pin));
			free(pin);
		}
		else {
			// PIN pad			
#ifdef _WIN32
			EstEID_log("creating pinpad dialog UI thread");
			pinpad_thread_result = -1;
			FAIL_IF_THREAD_ERROR("CreateMutex", (pinpad_thread_mutex = CreateMutex(NULL, FALSE, NULL)));
#else
			EstEID_log("creating pinpad worker thread");
			pinpad_thread_result = -1;
			FAIL_IF_PTHREAD_ERROR("pthread_mutex_init", pthread_mutex_init(&pinpad_thread_mutex, NULL));
			FAIL_IF_PTHREAD_ERROR("pthread_cond_init", pthread_cond_init(&pinpad_thread_condition, NULL));
			pthread_t pinpad_thread;
			EstEID_PINPadThreadData threadData;
			threadData.session = session;
			threadData.result = CKR_OK;
#endif
			EstEID_log("thread launched");
#ifdef _WIN32
			/*
			NB! Due to Firefox for Windows specific behaviour C_Login() is launched from main thread
			and UI code is running in separate thread if running on Windows.
			*/
			EstEID_PINPromptDataEx pinPromptDataEx;
			pinPromptDataEx.pinPromptData = pinPromptData;
			pinPromptDataEx.message = message;
			pinPromptDataEx.name = name;
			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EstEID_pinPadLogin, (LPVOID)&pinPromptDataEx, 0, NULL);
			loginResult = fl->C_Login(session, CKU_USER, NULL, 0);
			closePinPadModalSheet();
#else
			FAIL_IF_PTHREAD_ERROR("pthread_create", pthread_create(&pinpad_thread, NULL, EstEID_pinPadLogin, (void*)&threadData));
			pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, 0, isPinPad);
			loginResult = threadData.result;
#endif
			EstEID_log("pinpad sheet/dialog closed");			
			if (loginResult == CKR_FUNCTION_CANCELED) {
				setUserCancelErrorCodeAndMessage();				
				CLOSE_SESSION_AND_FAIL;				
			}
		}
		EstEID_log("loginResult = %s", pkcs11_error_message(loginResult));
		switch (loginResult) {
			case CKR_PIN_LOCKED:
				blocked = TRUE;
			case CKR_PIN_INCORRECT:
			case CKR_PIN_INVALID:
			case CKR_PIN_LEN_RANGE:
				EstEID_log("this was attempt %i, loginResult causes to run next round", attempt);
				continue;
			default:
				if (EstEID_CK_failure("C_Login", loginResult)) CLOSE_SESSION_AND_FAIL;
		}
		break; // Login successful - correct PIN supplied
	}

	if (name){
		free(name);
		name = NULL;
	}

	CK_OBJECT_CLASS objectClass = CKO_PRIVATE_KEY;
	CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)};
	if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) CLOSE_SESSION_AND_FAIL;

	CK_OBJECT_HANDLE privateKeyHandle;
	CK_ULONG objectCount;
	if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &privateKeyHandle, 1, &objectCount))) CLOSE_SESSION_AND_FAIL;
	if (EstEID_CK_failure("C_FindObjectsFinal", fl->C_FindObjectsFinal(session))) CLOSE_SESSION_AND_FAIL;

	if (objectCount == 0) CLOSE_SESSION_AND_FAIL; // todo ?? set error message

	CK_MECHANISM mechanism = {CKM_RSA_PKCS, 0, 0};
	if (EstEID_CK_failure("C_SignInit", fl->C_SignInit(session, &mechanism, privateKeyHandle))) CLOSE_SESSION_AND_FAIL;

	unsigned int hashWithPaddingLength;
	char *hashWithPadding = EstEID_addPadding(hash, hashLength, &hashWithPaddingLength);

	CK_ULONG len;
	if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, NULL, &len))) {
		free(hashWithPadding);
		CLOSE_SESSION_AND_FAIL;
	}
	*signature = (char *)malloc(len);
	if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, (CK_BYTE_PTR) * signature, &len))) {
		free(hashWithPadding);
		CLOSE_SESSION_AND_FAIL;
	}
	*signatureLength = len;
	free(hashWithPadding);

	if (session) {
		if (EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session))) {
			return FAILURE;
		}
	}
	
	EstEID_log("successfully signed");
	return SUCCESS;
}
コード例 #11
0
int testStability(CK_SLOT_ID slotID, CK_SESSION_HANDLE hSession, int rollovers, int batchjobs, int signatures, int sleepTime)
{
	CK_RV rv;
	int retVal = 0;
	CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
	CK_SESSION_HANDLE hSessionTmp;
	CK_BYTE_PTR pSignature = NULL;
        CK_ULONG ulSignatureLen = 0;
	CK_BYTE pData[] = {"Text"};
	CK_ULONG ulDataLen = sizeof(pData)-1;

	printf("\n********************************************************\n");
	printf("* Test for stability during key generation and signing *\n");
	printf("********************************************************\n\n");
	printf("This test will perform the following:\n\n");
	printf("* Key rollovers = %i\n", rollovers);
	printf("  The number of times that the key pair will be replaced.\n");
	printf("* Batchjobs = %i\n", batchjobs);
	printf("  The number of batchjobs for each key pair.\n");
	printf("* signatures = %i\n", signatures);
	printf("  Each batchjob will create signatures and verify them.\n");
	printf("* sleep time = %i\n", sleepTime);
	printf("  The process will sleep between the batchjobs.\n\n");

	for (int i = 0; i <= rollovers; i++)
	{
		// Generate key pair
		if (testStability_generate(hSession, &hPublicKey, &hPrivateKey))
		{
			retVal = 1;
			continue;
		}

		for (int j = 0; j < batchjobs; j++)
		{
			// Open Session
			rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSessionTmp);
			if (rv != CKR_OK)
			{
				printf("ERROR: Failed to open a session. rv=%s\n", rv2string(rv));
				retVal = 1;
				continue;
			}

			printf("Creating signatures and verifying them...\n");

			for (int k = 0; k < signatures; k++)
			{
				// Sign data
				if (testStability_sign(
					hSessionTmp,
					hPrivateKey,
					pData,
					ulDataLen,
					&pSignature,
					&ulSignatureLen))
				{
					retVal = 1;
					continue;
				}

				// Verify signature
				if (testStability_verify(
					hSessionTmp,
					hPublicKey,
					pData,
					ulDataLen,
					pSignature,
					ulSignatureLen))
				{
					retVal = 1;
				}

				// Clean up
				if (pSignature != NULL)
				{
					free(pSignature);
					pSignature = NULL;
					ulSignatureLen = 0;
				}
			}

			// Close session
			rv = p11->C_CloseSession(hSessionTmp);
			if (rv != CKR_OK)
			{
				printf("ERROR: Failed to close session. rv=%s\n", rv2string(rv));
				retVal = 1;
			}

			// Sleep
			printf("Sleeping for %i seconds...\n", sleepTime);
			sleep(sleepTime);
		}

		// Delete key pair
		printf("Deleting the key pair...\n");
		rv = p11->C_DestroyObject(hSession, hPublicKey);
		if (rv != CKR_OK)
		{
			printf("ERROR: Failed to delete the public key. rv=%s\n", rv2string(rv));
			retVal = 1;
		}
		rv = p11->C_DestroyObject(hSession, hPrivateKey);
		if (rv != CKR_OK)
		{
			printf("ERROR: Failed to delete the private key. rv=%s\n", rv2string(rv));
			retVal = 1;
		}
	}

	if (retVal == 0)
	{
		printf("\nThe test was performed successfully.\n");
	}
	else
	{
		printf("\nThe test was not performed successfully.\n");
	}

	return retVal;
}
コード例 #12
0
ファイル: sc.c プロジェクト: OldsSourcesBackups/kitty
CK_SESSION_HANDLE sc_get_session(void *f, int try_write_syslog, CK_FUNCTION_LIST_PTR fl,
                                 const char *token_label) {
#define SC_MAX_SLOT 16
    CK_SESSION_HANDLE session = 0;
    unsigned long slot_count = SC_MAX_SLOT;
    CK_TOKEN_INFO token_info;
    CK_SLOT_ID slots[SC_MAX_SLOT];
    CK_SLOT_ID c_slot = SC_MAX_SLOT;
    CK_SLOT_ID slot = SC_MAX_SLOT;
    CK_RV rv  = 0;
    int i;
    char msg[SC_STR_MAX_LEN] = "";

    if(fl == 0) {
        sprintf(msg, "sc: Invalid state, no function list");
        goto err;
    }
    rv = fl->C_GetSlotList(TRUE, slots, &slot_count);
    if(CKR_OK != rv) {
        sprintf(msg, "sc: C_GetSlotList failed 0x%.4x", (int)rv);
        goto err;
    }
    if(slot_count < 1) {
        sprintf(msg, "sc: No token available");
        goto err;
    }
    for(i=0; i<slot_count; i++) {
        slot = slots[i];
        rv = fl->C_GetTokenInfo(slot,&token_info);
        if (CKR_OK != rv) {
            sprintf(msg, "sc: C_GetTokenInfo failed for token in slot %i", i);
            goto err;
        }
        {
            char buf[40];
            memset(buf, 0, 40);
            int j;
            strncpy(buf, token_info.label, 30);
            for(j=29;j>0;j--) {
                if(buf[j] == ' ') {
                    buf[j] = '\0';
                } else {
                    break;
                }
            }
            sprintf(msg, "sc: Found token in slot %i: %s", i, buf);
            if(f) {
                logevent(f, msg);
                if(try_write_syslog) sc_write_syslog(msg);
            }
        }
        if(strncmp(token_label, token_info.label, strlen(token_label)) == 0) {
            c_slot = i;
            break;
        }
    }
    if(c_slot == 64) {
        sprintf(msg, "sc: No token named: %s", token_label);
        goto err;
    }              
    rv = fl->C_OpenSession(slots[c_slot],CKF_SERIAL_SESSION|CKF_RW_SESSION, 0, 0, &session);
    if (CKR_OK != rv) {
        sprintf(msg, "sc: C_OpenSession failed");
        goto err;
    } else {
        if(f) logevent(f, "sc: Session opened");
    }
    return session;
 err:
    if(f) {
        logevent(f, msg);
        if(try_write_syslog) sc_write_syslog(msg);
    }
    //  m_fl->C_Finalize(0);
    //  m_fl = 0;
    return 0;
}
コード例 #13
0
int EstEID_loadCertInfoEntries(EstEID_Certs *certs, int index) {
	EstEID_Map cert = certs->certs[index];
	CK_SLOT_ID slotID = certs->slotIDs[index];

	CK_SESSION_HANDLE session;
	FAIL_IF(EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session)));

	CK_OBJECT_CLASS objectClass = CKO_CERTIFICATE;
	CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)};
	if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) return FAILURE;

	CK_OBJECT_HANDLE objectHandle;
	CK_ULONG objectCount;
	if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &objectHandle, 1, &objectCount))) return FAILURE;

	if (objectCount == 0) return SUCCESS;

	CK_ATTRIBUTE attribute = {CKA_VALUE, NULL_PTR, 0};
	if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE;

	CK_ULONG certificateLength = attribute.ulValueLen;
	CK_BYTE_PTR certificate = (CK_BYTE_PTR)malloc(certificateLength);
	attribute.pValue = certificate;
	if (EstEID_CK_failure("C_GetAttributeValue", fl->C_GetAttributeValue(session, objectHandle, &attribute, 1))) return FAILURE;

	EstEID_mapPutNoAlloc(cert, strdup("certificateAsHex"), EstEID_bin2hex((char *)certificate, certificateLength));

	const unsigned char *p = certificate;
	X509 *x509 = d2i_X509(NULL, &p, certificateLength);
	
	char *certMD5;
	certMD5 = EstEID_getCertHash((char*)certificate);
	FAIL_IF(EstEID_md5_failure(certMD5));
	EstEID_mapPutNoAlloc(cert, strdup("certHash"), certMD5);
	free(certificate);
// todo: error handling of all openssl functions

	EstEID_mapPutNoAlloc(cert, strdup("validTo"), EstEID_ASN1_TIME_toString(X509_get_notAfter(x509)));
	EstEID_mapPutNoAlloc(cert, strdup("validFrom"), EstEID_ASN1_TIME_toString(X509_get_notBefore(x509)));

	unsigned long keyUsage;
	ASN1_BIT_STRING *usage = (ASN1_BIT_STRING *)X509_get_ext_d2i(x509, NID_key_usage, NULL, NULL);
	if (usage->length > 0) keyUsage = usage->data[0];
	ASN1_BIT_STRING_free(usage);

	if (keyUsage & X509v3_KU_DIGITAL_SIGNATURE) EstEID_mapPut(cert, "usageDigitalSignature", "TRUE");
	if (keyUsage & X509v3_KU_NON_REPUDIATION) {
		EstEID_mapPut(cert, "usageNonRepudiation", "TRUE");
		EstEID_mapPut(cert, "keyUsage", "Non-Repudiation");  // for compatibility with older plugin
	}

	EstEID_loadCertEntries(cert, "", X509_get_subject_name(x509));

	char *certSerialNumber = (char*)malloc(33);
	snprintf(certSerialNumber, 32, "%lX", ASN1_INTEGER_get(X509_get_serialNumber(x509)));
	EstEID_mapPutNoAlloc(cert, strdup("certSerialNumber"), certSerialNumber);
	EstEID_loadCertEntries(cert, "issuer.", X509_get_issuer_name(x509));

	BIO *bio = BIO_new(BIO_s_mem());
	if (!PEM_write_bio_X509(bio, x509)) printf("Cannot create PEM\n");
	char *b;
	int len = BIO_get_mem_data(bio, &b);
	char *pem = (char *)malloc(len + 1);
	strncpy(pem, b, len);
	pem[len] = 0;
	BIO_free(bio);
	EstEID_mapPutNoAlloc(cert, strdup("certificateAsPEM"), pem);

	FAIL_IF(EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session)));
	return SUCCESS;
}
コード例 #14
0
// Import a newly generated RSA1024 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10_RSA() {

  EVP_PKEY    *evp;
  RSA         *rsak;
  X509        *cert;
  ASN1_TIME   *tm;
  CK_BYTE     i, j;
  CK_BYTE     some_data[32];
  CK_BYTE     e[] = {0x01, 0x00, 0x01};
  CK_BYTE     p[64];
  CK_BYTE     q[64];
  CK_BYTE     dp[64];
  CK_BYTE     dq[64];
  CK_BYTE     qinv[64];
  BIGNUM      *e_bn;
  CK_ULONG    class_k = CKO_PRIVATE_KEY;
  CK_ULONG    class_c = CKO_CERTIFICATE;
  CK_ULONG    kt = CKK_RSA;
  CK_BYTE     id = 0;
  CK_BYTE     sig[64];
  CK_ULONG    recv_len;
  CK_BYTE     value_c[3100];
  CK_ULONG    cert_len;
  CK_BYTE     der_encoded[80];
  CK_BYTE_PTR der_ptr;
  CK_BYTE_PTR r_ptr;
  CK_BYTE_PTR s_ptr;
  CK_ULONG    r_len;
  CK_ULONG    s_len;

  unsigned char  *px;

  CK_ATTRIBUTE privateKeyTemplate[] = {
    {CKA_CLASS, &class_k, sizeof(class_k)},
    {CKA_KEY_TYPE, &kt, sizeof(kt)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_PUBLIC_EXPONENT, e, sizeof(e)},
    {CKA_PRIME_1, p, sizeof(p)},
    {CKA_PRIME_2, q, sizeof(q)},
    {CKA_EXPONENT_1, dp, sizeof(dp)},
    {CKA_EXPONENT_2, dq, sizeof(dq)},
    {CKA_COEFFICIENT, qinv, sizeof(qinv)}
  };

  CK_ATTRIBUTE publicKeyTemplate[] = {
    {CKA_CLASS, &class_c, sizeof(class_c)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_VALUE, value_c, sizeof(value_c)}
  };

  CK_OBJECT_HANDLE obj[24];
  CK_SESSION_HANDLE session;
  CK_MECHANISM mech = {CKM_RSA_PKCS, NULL};

  evp = EVP_PKEY_new();

  if (evp == NULL)
    exit(EXIT_FAILURE);

  rsak = RSA_new();

  if (rsak == NULL)
    exit(EXIT_FAILURE);

  e_bn = BN_bin2bn(e, 3, NULL);

  if (e_bn == NULL)
    exit(EXIT_FAILURE);

  asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK");

  asrt(BN_bn2bin(rsak->p, p), 64, "GET P");
  asrt(BN_bn2bin(rsak->q, q), 64, "GET Q");
  asrt(BN_bn2bin(rsak->dmp1, dp), 64, "GET DP");
  asrt(BN_bn2bin(rsak->dmq1, dp), 64, "GET DQ");
  asrt(BN_bn2bin(rsak->iqmp, qinv), 64, "GET QINV");



  if (EVP_PKEY_set1_RSA(evp, rsak) == 0)
    exit(EXIT_FAILURE);

  cert = X509_new();

  if (cert == NULL)
    exit(EXIT_FAILURE);

  if (X509_set_pubkey(cert, evp) == 0)
    exit(EXIT_FAILURE);

  tm = ASN1_TIME_new();
  if (tm == NULL)
    exit(EXIT_FAILURE);

  ASN1_TIME_set_string(tm, "000001010000Z");
  X509_set_notBefore(cert, tm);
  X509_set_notAfter(cert, tm);

  cert->sig_alg->algorithm = OBJ_nid2obj(8);
  cert->cert_info->signature->algorithm = OBJ_nid2obj(8);

  ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
  ASN1_BIT_STRING_set(cert->signature, "\x00", 1);

  px = value_c;
  if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c))
    exit(EXIT_FAILURE);

  publicKeyTemplate[2].ulValueLen = cert_len;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
  asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");

  for (i = 0; i < 24; i++) {
    id = i;
    asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
    asrt(funcs->C_CreateObject(session, privateKeyTemplate, 9, obj + i), CKR_OK, "IMPORT KEY");
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");

  for (i = 0; i < 24; i++) {
    for (j = 0; j < 10; j++) {

      if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
        exit(EXIT_FAILURE);

      asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
      asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");

      recv_len = sizeof(sig);
      asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");

      /* r_len = 32; */
      /* s_len = 32; */

      /* der_ptr = der_encoded; */
      /* *der_ptr++ = 0x30; */
      /* *der_ptr++ = 0xff; // placeholder, fix below */

      /* r_ptr = sig; */

      /* *der_ptr++ = 0x02; */
      /* *der_ptr++ = r_len; */
      /* if (*r_ptr >= 0x80) { */
      /*   *(der_ptr - 1) = *(der_ptr - 1) + 1; */
      /*   *der_ptr++ = 0x00; */
      /* } */
      /* else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) { */
      /*   r_len--; */
      /*   *(der_ptr - 1) = *(der_ptr - 1) - 1; */
      /*   r_ptr++; */
      /* } */
      /* memcpy(der_ptr, r_ptr, r_len); */
      /* der_ptr+= r_len; */

      /* s_ptr = sig + 32; */

      /* *der_ptr++ = 0x02; */
      /* *der_ptr++ = s_len; */
      /* if (*s_ptr >= 0x80) { */
      /*   *(der_ptr - 1) = *(der_ptr - 1) + 1; */
      /*   *der_ptr++ = 0x00; */
      /* } */
      /* else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) { */
      /*   s_len--; */
      /*   *(der_ptr - 1) = *(der_ptr - 1) - 1; */
      /*   s_ptr++; */
      /* } */
      /* memcpy(der_ptr, s_ptr, s_len); */
      /* der_ptr+= s_len; */

      /* der_encoded[1] = der_ptr - der_encoded - 2; */

      /* dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1); */

      /* asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION"); */

      }
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");

  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}
コード例 #15
0
// Import a newly generated P256 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10() {

  EVP_PKEY       *evp;
  EC_KEY         *eck;
  const EC_POINT *ecp;
  const BIGNUM   *bn;
  char           pvt[32];
  X509           *cert;
  ASN1_TIME      *tm;
  CK_BYTE        i, j;
  CK_BYTE        some_data[32];

  CK_ULONG    class_k = CKO_PRIVATE_KEY;
  CK_ULONG    class_c = CKO_CERTIFICATE;
  CK_ULONG    kt = CKK_ECDSA;
  CK_BYTE     id = 0;
  CK_BYTE     params[] = {0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
  CK_BYTE     sig[64];
  CK_ULONG    recv_len;
  CK_BYTE     value_c[3100];
  CK_ULONG    cert_len;
  CK_BYTE     der_encoded[80];
  CK_BYTE_PTR der_ptr;
  CK_BYTE_PTR r_ptr;
  CK_BYTE_PTR s_ptr;
  CK_ULONG    r_len;
  CK_ULONG    s_len;

  unsigned char  *p;

  CK_ATTRIBUTE privateKeyTemplate[] = {
    {CKA_CLASS, &class_k, sizeof(class_k)},
    {CKA_KEY_TYPE, &kt, sizeof(kt)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_EC_PARAMS, &params, sizeof(params)},
    {CKA_VALUE, pvt, sizeof(pvt)}
  };

  CK_ATTRIBUTE publicKeyTemplate[] = {
    {CKA_CLASS, &class_c, sizeof(class_c)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_VALUE, value_c, sizeof(value_c)}
  };

  CK_OBJECT_HANDLE obj[24];
  CK_SESSION_HANDLE session;
  CK_MECHANISM mech = {CKM_ECDSA, NULL};

  evp = EVP_PKEY_new();

  if (evp == NULL)
    exit(EXIT_FAILURE);

  eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

  if (eck == NULL)
    exit(EXIT_FAILURE);

  asrt(EC_KEY_generate_key(eck), 1, "GENERATE ECK");

  bn = EC_KEY_get0_private_key(eck);

  asrt(BN_bn2bin(bn, pvt), 32, "EXTRACT PVT");

  if (EVP_PKEY_set1_EC_KEY(evp, eck) == 0)
    exit(EXIT_FAILURE);

  cert = X509_new();

  if (cert == NULL)
    exit(EXIT_FAILURE);

  if (X509_set_pubkey(cert, evp) == 0)
    exit(EXIT_FAILURE);

  tm = ASN1_TIME_new();
  if (tm == NULL)
    exit(EXIT_FAILURE);

  ASN1_TIME_set_string(tm, "000001010000Z");
  X509_set_notBefore(cert, tm);
  X509_set_notAfter(cert, tm);

  cert->sig_alg->algorithm = OBJ_nid2obj(8);
  cert->cert_info->signature->algorithm = OBJ_nid2obj(8);

  ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
  ASN1_BIT_STRING_set(cert->signature, "\x00", 1);

  p = value_c;
  if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c))
    exit(EXIT_FAILURE);

  publicKeyTemplate[2].ulValueLen = cert_len;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
  asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");

  for (i = 0; i < 24; i++) {
    id = i;
    asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
    asrt(funcs->C_CreateObject(session, privateKeyTemplate, 5, obj + i), CKR_OK, "IMPORT KEY");
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");

  for (i = 0; i < 24; i++) {
    for (j = 0; j < 10; j++) {

      if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
        exit(EXIT_FAILURE);

      asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
      asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");

      recv_len = sizeof(sig);
      asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");

      r_len = 32;
      s_len = 32;

      der_ptr = der_encoded;
      *der_ptr++ = 0x30;
      *der_ptr++ = 0xff; // placeholder, fix below

      r_ptr = sig;

      *der_ptr++ = 0x02;
      *der_ptr++ = r_len;
      if (*r_ptr >= 0x80) {
        *(der_ptr - 1) = *(der_ptr - 1) + 1;
        *der_ptr++ = 0x00;
      }
      else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) {
        r_len--;
        *(der_ptr - 1) = *(der_ptr - 1) - 1;
        r_ptr++;
      }
      memcpy(der_ptr, r_ptr, r_len);
      der_ptr+= r_len;

      s_ptr = sig + 32;

      *der_ptr++ = 0x02;
      *der_ptr++ = s_len;
      if (*s_ptr >= 0x80) {
        *(der_ptr - 1) = *(der_ptr - 1) + 1;
        *der_ptr++ = 0x00;
      }
      else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) {
        s_len--;
        *(der_ptr - 1) = *(der_ptr - 1) - 1;
        s_ptr++;
      }
      memcpy(der_ptr, s_ptr, s_len);
      der_ptr+= s_len;

      der_encoded[1] = der_ptr - der_encoded - 2;

      dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1);

      asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION");

      }
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");

  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}