コード例 #1
0
static void test_lib_info() {

  const CK_CHAR_PTR MANUFACTURER_ID    = "Yubico (www.yubico.com)";
  const CK_CHAR_PTR YKCS11_DESCRIPTION = "PKCS#11 PIV Library (SP-800-73)";
  const CK_ULONG CRYPTOKI_VERSION_MAJ  = 2;
  const CK_ULONG CRYPTOKI_VERSION_MIN  = 40;


  CK_INFO info;

  asrt(funcs->C_GetInfo(&info), CKR_OK, "GET_INFO");

  asrt(strcmp(info.manufacturerID, MANUFACTURER_ID), 0, "MANUFACTURER");

  asrt(info.cryptokiVersion.major, CRYPTOKI_VERSION_MAJ, "CK_MAJ");
  asrt(info.cryptokiVersion.minor, CRYPTOKI_VERSION_MIN, "CK_MIN");

  asrt(info.libraryVersion.major, YKCS11_VERSION_MAJOR, "LIB_MAJ");
  asrt(info.libraryVersion.minor, ((YKCS11_VERSION_MINOR * 10) + YKCS11_VERSION_PATCH ), "LIB_MIN");

  asrt(strcmp(info.libraryDescription, YKCS11_DESCRIPTION), 0, "LIB_DESC");
}
コード例 #2
0
ファイル: ykcs11_tests.c プロジェクト: akgood/yubico-piv-tool
static void lib_info() {

  CK_INFO info;
  CK_FUNCTION_LIST_PTR funcs;

  if (C_GetFunctionList(&funcs) != CKR_OK) {
    fprintf(stderr, "Get function list failed\n");
    exit(EXIT_FAILURE);
  }

  if (funcs->C_GetInfo(&info) != CKR_OK) {
    fprintf(stderr, "GetInfo failed\n");
    exit(EXIT_FAILURE);
  }

  if (strcmp(info.manufacturerID, MANUFACTURER_ID) != 0) {
    fprintf(stderr, "unexpected manufacturer ID %s\n", info.manufacturerID);
    exit(EXIT_FAILURE);
  }

  if (info.cryptokiVersion.major != CRYPTOKI_VERSION_MAJ ||
      info.cryptokiVersion.minor != CRYPTOKI_VERSION_MIN ) {
    fprintf(stderr, "unexpected Cryptoki version %d.%d\n", info.cryptokiVersion.major, info.cryptokiVersion.minor);
    exit(EXIT_FAILURE);
  }

  if (info.libraryVersion.major != YKCS11_VERSION_MAJOR ||
      info.libraryVersion.minor != ((YKCS11_VERSION_MINOR * 100) + YKCS11_VERSION_PATCH )) {
    fprintf(stderr, "unexpected YKCS11 version %d.%d\n", info.libraryVersion.major, info.libraryVersion.minor);
    exit(EXIT_FAILURE);
  }

  if (strcmp(info.libraryDescription, YKCS11_DESCRIPTION) != 0) {
    fprintf(stderr, "unexpected description %s\n", info.libraryDescription);
    exit(EXIT_FAILURE);
  }

}
コード例 #3
0
THREAD_RETURN_TYPE EstEID_initializeCryptokiThread(void *v) {
	LOG_LOCATION;	
#ifdef _WIN32
	WaitForSingleObject(initialization_mutex, INFINITE);
#else
	pthread_mutex_lock(&initialization_mutex);
#endif	
	CK_C_INITIALIZE_ARGS  init_args;
	memset( &init_args, 0x0, sizeof(init_args) );
	init_args.flags = CKF_OS_LOCKING_OK;

	struct timeval start = EstEID_startTimer();
	initialization_result = fl->C_Initialize(&init_args);
	EstEID_log("C_Initialize: %s (%li)", pkcs11_error_message(initialization_result), initialization_result);
	EstEID_stopTimerAndLog(start, "C_Initialize:");

	if (initialization_result == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
		EstEID_log("initialization_result == CKR_CRYPTOKI_ALREADY_INITIALIZED");
	}

	if (initialization_result == CKR_OK) {
		CK_INFO info;
		EstEID_log("initialization_result == CKR_OK");
		if (!EstEID_CK_failure("C_GetInfo", fl->C_GetInfo(&info))) {
			EstEID_logInitInfo(info);
		};
	}
	initialization_completed = TRUE;
#ifdef _WIN32
	ReleaseMutex(initialization_mutex);
	return TRUE;
#else
	pthread_cond_broadcast(&initialization_condition);
	pthread_mutex_unlock(&initialization_mutex);
	pthread_exit(NULL);
#endif
}
コード例 #4
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;
}
コード例 #5
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;
	}
}