Ejemplo n.º 1
0
/**
 * Create a new DGN token if token detection and initialization is successful
 *
 * @param slot      The slot in which a token was detected
 * @param token     Pointer to pointer updated with newly created token structure
 * @return          CKR_OK or any other Cryptoki error code
 */
static int newDGNToken(struct p11Slot_t *slot, struct p11Token_t **token)
{
	static struct p11TokenDriver esign_token;
	struct p11Token_t *ptoken;
	struct p11TokenDriver *drv;
	struct p11Slot_t *vslot;
	int rc;

	FUNC_CALLED();

	esign_token = *getStarcosTokenDriver();
	esign_token.name = "3.5ID ECC C1 DGN";
	esign_token.isCandidate = isCandidate;
	esign_token.newToken = newDGNToken;
	esign_token.C_Sign = esign_C_Sign;

	rc = createStarcosToken(slot, &ptoken, &esign_token, &starcosApplications[1]);
	if (rc != CKR_OK)
		FUNC_FAILS(rc, "Base token creation failed");

	rc = addToken(slot, ptoken);
	if (rc != CKR_OK) {
		FUNC_FAILS(rc, "addToken() failed");
	}

	*token = ptoken;

	if (context->caller == CALLER_FIREFOX) {
		FUNC_RETURNS(CKR_OK);
	}

	rc = getVirtualSlot(slot, 0, &vslot);
	if (rc != CKR_OK)
		FUNC_FAILS(rc, "Virtual slot creation failed");

	drv = getDGNTokenDriver();
	rc = createStarcosToken(vslot, &ptoken, drv, &starcosApplications[0]);
	if (rc != CKR_OK)
		FUNC_FAILS(rc, "Token creation failed");

	rc = addToken(vslot, ptoken);
	if (rc != CKR_OK)
		FUNC_FAILS(rc, "addToken() failed");

	FUNC_RETURNS(CKR_OK);
}
Ejemplo n.º 2
0
int updatePCSCSlots(struct p11SlotPool_t *pool)
{
	struct p11Slot_t *slot,*vslot;
	LPTSTR readers = NULL;
	char *filter, *prealloc;
	DWORD cch = 0;
//	DWORD cch = SCARD_AUTOALLOCATE;
	LPTSTR p;
	LONG rc;
	int match,vslotcnt,i;

	FUNC_CALLED();

	/*
	 * Create a context if not already done
	 */
	if (!globalContext) {

		rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &globalContext);

#ifdef DEBUG
		debug("SCardEstablishContext: %s\n", pcsc_error_to_string(rc));
#endif

		if (rc != SCARD_S_SUCCESS) {
			FUNC_FAILS(CKR_DEVICE_ERROR, "Could not establish context to PC/SC manager");
		}
	}

	rc = SCardListReaders(globalContext, NULL, NULL, &cch);

#ifdef DEBUG
	debug("SCardListReaders: %s\n", pcsc_error_to_string(rc));
#endif

	if (rc == SCARD_E_NO_READERS_AVAILABLE) {
		FUNC_RETURNS(CKR_OK);
	}

	if (rc != SCARD_S_SUCCESS) {
		FUNC_FAILS(CKR_DEVICE_ERROR, "Error listing PC/SC card terminals");
	}

	readers = calloc(cch, 1);

	rc = SCardListReaders(globalContext, NULL, readers, &cch);

#ifdef DEBUG
	debug("SCardListReaders: %s\n", pcsc_error_to_string(rc));
#endif

	if (rc == SCARD_E_NO_READERS_AVAILABLE) {
		FUNC_RETURNS(CKR_OK);
	}

	if (rc != SCARD_S_SUCCESS) {
		FUNC_FAILS(CKR_DEVICE_ERROR, "Error listing PC/SC card terminals");
	}
	
	filter = getenv("PKCS11_READER_FILTER");
#ifdef DEBUG
	if (filter) {
		debug("Reader filter '%s'\n", filter);
	}
#endif

	/* Determine the total number of readers */
	p = readers;
	while (*p != '\0') {
#ifdef DEBUG
		debug("Found reader '%s'\n", p);
#endif

		/* Check if we already have a slot for the reader */
		slot = pool->list;
		match = FALSE;
		while (slot) {
			if (strncmp(slot->readername, p, strlen(p)) == 0) {
				match = TRUE;
				break;
			}
			slot = slot->next;
		}

		/* Skip the reader as we already have a slot for it */
		if (match) {
			p += strlen(p) + 1;
			slot->closed = FALSE;
			continue;
		}

		if (!matchFilter(p, filter)) {
			p += strlen(p) + 1;
			continue;
		}

		slot = (struct p11Slot_t *) calloc(1, sizeof(struct p11Slot_t));

		if (slot == NULL) {
			free(readers);
			FUNC_FAILS(CKR_HOST_MEMORY, "Out of memory");
		}

		/* If a reader filter is defined, then slot ids for that reader are
		 * derived from the reader name using a CRC32 value. If the token
		 * in the reader allocated virtual slots, then these have incremented
		 * slot ids.
		 *
		 * This is not enabled by default to prevent slot id collisions
		 */
		if (filter)
			slot->id = crc32(0, p, strlen(p));

		rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &(slot->context));

#ifdef DEBUG
		debug("SCardEstablishContext: %s\n", pcsc_error_to_string(rc));
#endif

		if (rc != SCARD_S_SUCCESS) {
			free(slot);
			free(readers);
			FUNC_FAILS(CKR_DEVICE_ERROR, "Could not establish context to PC/SC manager");
		}

		slotCounter++;

		strbpcpy(slot->info.slotDescription,
				(char *)p,
				sizeof(slot->info.slotDescription));

		strcpy(slot->readername, (char *)p);

		strbpcpy(slot->info.manufacturerID,
				"CardContact",
				sizeof(slot->info.manufacturerID));

		slot->info.hardwareVersion.minor = 0;
		slot->info.hardwareVersion.major = 0;

		slot->info.firmwareVersion.major = VERSION_MAJOR;
		slot->info.firmwareVersion.minor = VERSION_MINOR;

		slot->info.flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;

		// The REINER SCT readers have an APDU buffer limitation of 1014 bytes
		if (!strncmp((char *)p, "REINER SCT", 10)) {
#ifdef DEBUG
			debug("Detected a REINER SCT reader\n");
#endif
			if (!strncmp((char *)p, "REINER SCT cyberJack ecom_a", 27)) {
#ifdef DEBUG
				debug("Detected a 'REINER SCT cyberJack ecom_a' reader. Limiting use of Le='000000'\n");
#endif
				// Some REINER SCT readers fail if Le='000000' returns more than
				// 1014 bytes.
				slot->noExtLengthReadAll = 1;
			}
			slot->maxRAPDU = 1000;
			slot->maxCAPDU = 1000;
		}

		addSlot(&context->slotPool, slot);

#ifdef DEBUG
		debug("Added slot (%lu, %s) - slot counter is %i\n", slot->id, slot->readername, slotCounter);
#endif

		// The PREALLOCATE option creates two additional virtual slots per card reader.
		// This is required for Firefox/NSS which sets the friendly flag only for slots that are
		// already present during the first C_GetSlotList
		prealloc = getenv("PKCS11_PREALLOCATE_VIRTUAL_SLOTS");
		if (prealloc) {
			vslotcnt = *prealloc;
			if ((vslotcnt == '1') || (vslotcnt == '2')) {
				vslotcnt -= '0';
			} else {
				vslotcnt = 2;
			}
#ifdef DEBUG
			debug("Pre-allocate virtual slots '' %d\n", prealloc, vslotcnt);
#endif
			for (i = 0; i < vslotcnt; i++) {
				getVirtualSlot(slot, i, &vslot);
			}
		}

		checkForNewPCSCToken(slot);

		p += strlen(p) + 1;
	}

	free(readers);

	FUNC_RETURNS(CKR_OK);
}