Exemple #1
0
/* TODO : this function hasn't really been tested                */
int
readerGetContactlessStatus(
                            tReaderManager  *pManager,
                            tReader	        *pReader
                          )
{
    DWORD		dwRecvLength;
    BYTE		pbRecvBuffer[20];
    LONG		rv;
    int         i;
    BOOL        automatic;

    /* Duh. If you pass me a NULL pointer then I'm out of here */
    if ( ( pManager == NULL ) || ( pManager->hContext == NULL ) )
       return( SCARD_E_INVALID_PARAMETER );

    automatic = readersSettingBitmapBitTest( pManager, READER_BIT_AUTO );

    if ( automatic )
    {
        /* re-enumerate the readers in the system as it may have changed */
        rv = readersConnect( pManager );
        if ( rv != SCARD_S_SUCCESS )
            return( rv );
    }

    sprintf(messageString, "Requesting contactles status");
    readersLogMessage( pManager, LOG_INFO, 2, messageString);

    /* then check all readers we were ABLE to connect to */
    for ( i = 0; i < pManager->nbReaders; i++ )
    {
        /* check we have connected and have a driver for this reader */
        if ( ( pReader[i].hCard != NULL ) && ( pReader[i].pDriver != NULL ) &&
             ( automatic || readersSettingBitmapNumberTest( pManager, i ) ) )
        {
            dwRecvLength = sizeof(pbRecvBuffer);
            rv = ((tReaderDriver *)(pReader[i].pDriver))->getContactlessStatus(pReader, pbRecvBuffer, &dwRecvLength);

            if ( rv == SCARD_S_SUCCESS )
            {
                if (pManager->libVerbosityLevel)
                {
                    sprintf(messageString, "Reader %d Status: ", i);
                    sPrintBufferHex( (messageString + strlen("Reader %d Status: ") ), dwRecvLength, pbRecvBuffer);
                    readersLogMessage( pManager, LOG_INFO, 2, messageString);

                    sprintf(messageString, "Number of Tags = %d", pbRecvBuffer[4]);
                    readersLogMessage( pManager, LOG_INFO, 2, messageString);
                }
            }
            else
                PCSC_ERROR( pManager, rv, "driver->getConnectlessStatus:");
        }
    }

   return (rv);
}
Exemple #2
0
/* we can detect in this reader                                  */
LONG   acr122UGetTagList(
    tReader	    *pReader,
    tTag	        pTags[]
    /* an array of tags that will be filled */
    /* this must to the max specified */
    /* in the driver structure */
)
{
    LONG			rv;
    DWORD		    dwRecvLength;
    BYTE			pbRecvBuffer[40]; /* TODO find a constant for the max size */

    int			    i, other;
    BOOL			known, processTag;

    pReader->tagList.numTags = 0;

    /* This reader has some wierd behaviour, in that sometimes the ONLY tag is  */
    /* reported on the SECOND call to poll it not the first that is why we write*/
    /* into the array using pReader->tagList.numTags as an index, and not 'i'   */

    /* loop until we have read possible number of unique tags on the reader */
    for (i = 0; i < ACR122U_MAX_NUM_TAGS; i++)
    {
        /* we are not going to read ANY tag's contents and so it's a NULL pointer */
        pTags[i].contents.pData = NULL;
        pTags[i].contents.dataSize = 0;
        pTags[i].contents.extensionHook = NULL;

        dwRecvLength = sizeof(pbRecvBuffer);
        rv = apduSend(pReader->hCard, APDU_POLL_MIFARE, sizeof(APDU_POLL_MIFARE),
                      pbRecvBuffer, &dwRecvLength);
        if (rv == SCARD_S_SUCCESS)
        {
            processTag = FALSE;

            /* ACS_TAG_FOUND = {0xD5, 0x4B}  */
            if ( (pbRecvBuffer[SW1] == 0xD5) &&
                    (pbRecvBuffer[SW2] == 0x4B) &&
                    (pbRecvBuffer[NUM_TAGS_FOUND] != 0x00) ) /* not sure it reports 2 when there are 2 */
            {
                /* how the rest is organized depends on tag Type */
                switch ( pbRecvBuffer[SEL_RES_BYTE] )
                {
                case SEL_RES_MIFARE_ULTRA:
                case SEL_RES_MIFARE_1K:
                case SEL_RES_MIFARE_MINI:      /* not sure but I think so */
                case SEL_RES_MIFARE_4K:
                case SEL_RES_MIFARE_DESFIRE:
                    /* the uid is in the next 'uid_length' number bytes */
                    sPrintBufferHex(pTags[pReader->tagList.numTags].uid,
                                    pbRecvBuffer[UID_LENGTH], (pbRecvBuffer + UID_START) );
                    /* store tag type in tag struct */
                    pTags[pReader->tagList.numTags].tagType = (tTagType)(pbRecvBuffer[SEL_RES_BYTE]);
                    processTag = TRUE;
                    break;

                case SEL_RES_JCOP30:
                    pTags[pReader->tagList.numTags].tagType = (tTagType)(pbRecvBuffer[SEL_RES_BYTE]);
                    sprintf( pTags[pReader->tagList.numTags].uid, "UID Unknown" );
                    break;

                case SEL_RES_GEMPLUS_MPCOS:
                    pTags[pReader->tagList.numTags].tagType = (tTagType)(pbRecvBuffer[SEL_RES_BYTE]);
                    sprintf( pTags[pReader->tagList.numTags].uid, "UID Unknown" );
                    break;

                default:
                    pTags[pReader->tagList.numTags].tagType = UNKNOWN_TYPE;
                    sprintf( pTags[pReader->tagList.numTags].uid, "UID Unknown" );
                    break;
                }

                /* avoid processing tags we don't know enough about */
                if ( processTag )
                {
                    /* TODO look into using the TARGET_NUMBER byte returned... */
                    /* first one ? */
                    if ( i == 0 )
                        (pReader->tagList.numTags)++; /* got first one */
                    else
                    {
                        /* check if this ID is already in our list - avoid duplication */
                        known = FALSE;
                        for (other = 0; ((other < pReader->tagList.numTags) && (!known)) ; other++)
                        {
                            /* is this tag id already in this reader's list? */
                            if (strcmp(pTags[i].uid, pTags[other].uid) == 0)
                                known = TRUE;
                        }

                        if (!known)
                            (pReader->tagList.numTags)++; /* got another one */
                    }
                }
            }
        }
        else
            return (rv);
    } /* for */

    return (rv);

}
Exemple #3
0
/************************ READER CHECK ***************************/
LONG   acr122UReaderCheck(
    tReader   *pReader,
    BOOL      *pReaderSupported
)
{
    static  char     pbReader[MAX_READERNAME] = "";

    DWORD  dwAtrLen, dwReaderLen, dwState, dwProt;
    DWORD  dwRecvLength;
    BYTE   pbAtr[MAX_ATR_SIZE] = "";
    int    i;
    LONG   rv;
    BYTE	  pbRecvBuffer[MAX_FIRMWARE_STRING_LENGTH];

    *pReaderSupported = FALSE;

    /* First check the name reported by pcscd to see if it's possible supported */
    for (i = 0; (i < SUPPORTED_READER_NAME_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++)
    {
        if ( strncmp( pReader->name, SUPPORTED_READER_NAME_ARRAY[i],
                      sizeof(SUPPORTED_READER_NAME_ARRAY[i])-1) == 0 )
            *pReaderSupported = TRUE;
    }

    /* If even the name is not supported, then we're done */
    if ( *pReaderSupported == FALSE )
        return (SCARD_S_SUCCESS );

    /* just because the name was OK, doesn't mean it'll actually work! */
    *pReaderSupported = FALSE;

    /* Get firmware version and check it's really a ACR122* */
    dwRecvLength = sizeof(pbRecvBuffer);
    rv = apduSend(pReader->hCard, APDU_GET_READER_FIRMWARE,
                  sizeof(APDU_GET_READER_FIRMWARE),
                  pbRecvBuffer, &dwRecvLength);
    if (rv != SCARD_S_SUCCESS)
        return (rv);

    /* Search the list of supported firmware versions (reader versions) */
    /* to check we are compatible with it - or have tested with it      */

    /* NULL terminate the BYTE array for subsequent string compares */
    pbRecvBuffer[dwRecvLength] = '\0';

    for (i = 0; (i < SUPPORTED_READER_FIRMWARE_ARRAY_COUNT) & (*pReaderSupported == FALSE) ; i++)
    {
        if ( strncmp( ((char *)pbRecvBuffer), SUPPORTED_READER_FIRMWARE_ARRAY[i],
                      sizeof(SUPPORTED_READER_FIRMWARE_ARRAY[i])-1) == 0 )
            *pReaderSupported = TRUE;
    }

    /* if we didn't find that we support it, then we're done */
    if ( *pReaderSupported == FALSE )
        return( SCARD_S_SUCCESS ); /* no actual communication errors to report */

    /* If we got this far then the general name and specific firmware version is supported */
    /* Get ATR so we can tell if there is a SAM in the reader */
    dwAtrLen = sizeof(pbAtr);
    dwReaderLen = sizeof(pbReader);
    SCardStatus( (SCARDHANDLE) (pReader->hCard), pbReader, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen);

    dwRecvLength = sizeof(pbRecvBuffer);
    rv = apduSend(pReader->hCard, APDU_SET_RETRY, sizeof(APDU_SET_RETRY),
                  pbRecvBuffer, &dwRecvLength);
    if (rv != SCARD_S_SUCCESS)
        return (rv);

    /* get card status ATR first two bytes = ACS_NO_SAM= '3B00' */
    if ( (pbAtr[SW1] != 0x3B) || (pbAtr[SW2] != 0x00) )
    {
        dwRecvLength = sizeof(pbRecvBuffer);
        rv = apduSend(pReader->hCard, APDU_GET_SAM_SERIAL,
                      sizeof(APDU_GET_SAM_SERIAL),
                      pbRecvBuffer, &dwRecvLength);
        if (rv == SCARD_S_SUCCESS)
        {
            sPrintBufferHex(pReader->SAM_serial, dwRecvLength, pbRecvBuffer);
#if 0
            sprintf(messageString, "SAM Serial: %s", pReader->SAM_serial);
            readersLogMessage(LOG_INFO, 1, messageString);
#endif
        }
        else
            return (rv);

        dwRecvLength = sizeof(pbRecvBuffer);
        rv = apduSend(pReader->hCard, APDU_GET_SAM_ID, sizeof(APDU_GET_SAM_ID),
                      pbRecvBuffer, &dwRecvLength);
        if (rv == SCARD_S_SUCCESS)
        {
            sPrintBufferHex(pReader->SAM_id, dwRecvLength, pbRecvBuffer);
#if 0
            sprintf(messageString, "SAM ID: %s", pReader->SAM_id);
            readersLogMessage(LOG_INFO, 1, messageString);
#endif
        }
        else
            return( rv );

        pReader->SAM = TRUE;
    }

    /* Turning RATS off thus a JCOP tag will be detected as emulating a DESFIRE */
    apduSend(pReader->hCard, APDU_RATS_14443_4_OFF, sizeof(APDU_RATS_14443_4_OFF), pbRecvBuffer, &dwRecvLength);

    return( SCARD_S_SUCCESS );

}
Exemple #4
0
/**************************** APDU SEND ************************/
static LONG
apduSend (
    tCardHandle     hCard,
    const BYTE    	*apdu,
    DWORD			apduLength,
    BYTE			*pbRecvBuffer,
    DWORD			*dwRecvLength
)
{
    LONG 			rv;
    SCARD_IO_REQUEST 	pioRecvPci;
    BYTE 			pbSendBuffer[40];
    DWORD 			dwSendLength = 0;
    DWORD			rBufferMax;
    BOOL			psuedoAPDU = FALSE;


    /* remember the size of the input buffer passed to us, so we don't exceed */
    rBufferMax = *dwRecvLength;

    /* The special psuedo APDU's to talk to a tag, need to have their */
    /* response read back in two chunks, using GET_RESPONSE for the second */
    if (apdu[0] == 0xd4)
    {
        psuedoAPDU = TRUE;
        /* prepend the DIRECT_TRANSMIT APDU  */
        memcpy(pbSendBuffer, APDU_DIRECT_TRANSMIT, sizeof(APDU_DIRECT_TRANSMIT));

        /* then a byte that tells it the length of the psuedo APDU to follow */
        pbSendBuffer[sizeof(APDU_DIRECT_TRANSMIT)] = (BYTE)apduLength;

        dwSendLength += (sizeof(APDU_DIRECT_TRANSMIT) + 1);
    }

    /* Add the APDU that was requested to be sent and increase length to send */
    memcpy((pbSendBuffer + dwSendLength), apdu, apduLength);
    dwSendLength += apduLength;

#if 0
    sprintf(messageString, "APDU: ");
    sPrintBufferHex((messageString + strlen("APDU: ")), dwSendLength, pbSendBuffer);
    readersLogMessage( pManager, LOG_INFO, 3, messageString);
#endif

    rv = SCardTransmit((SCARDHANDLE) hCard,
                       pioSendPci, pbSendBuffer, dwSendLength,
                       &pioRecvPci, pbRecvBuffer, dwRecvLength);

    /* if it was a psuedo APDU then we need to get the response */
    if ( (rv == SCARD_S_SUCCESS) && psuedoAPDU )
    {
#if 0
        sprintf(messageString, "Received: ");
        sPrintBufferHex((messageString + strlen("Received: ")), *dwRecvLength, pbRecvBuffer);
        readersLogMessage(LOG_INFO, 3, messageString);
#endif

        /* command went OK? */
        if (pbRecvBuffer[SW1] != SW1_SUCCESS)
        {
#if 0
            sprintf(messageString, "APDU failed: SW1 = %02X", pbRecvBuffer[SW1]);
            readersLogMessage(LOG_ERR, 0, messageString);
#endif
            return ( SCARD_F_COMM_ERROR );
        }

        /* are their response bytes to get? */
        if (pbRecvBuffer[SW2] > 0)
        {
#if 0
            sprintf(messageString, "Requesting Response Data (%d)",
                    pbRecvBuffer[SW2]);
            readersLogMessage(LOG_INFO, 3, messageString);
#endif

            /* copy the get_response APDU into the first bytes */
            memcpy(pbSendBuffer, APDU_GET_RESPONSE, sizeof(APDU_GET_RESPONSE));

            /* the second response byte tells us how many bytes are pending */
            /* add that value at the end of the GET_RESPONSE APDU */
            pbSendBuffer[sizeof(APDU_GET_RESPONSE)] = pbRecvBuffer[SW2];
            dwSendLength = sizeof(APDU_GET_RESPONSE) + 1;

            /* specify the maximum size of the buffer that was passed in */
            *dwRecvLength = rBufferMax;

            rv = SCardTransmit((SCARDCONTEXT)hCard, pioSendPci, pbSendBuffer,
                               dwSendLength, &pioRecvPci, pbRecvBuffer, dwRecvLength );
#if 0
            PCSC_ERROR(rv, "SCardTransmit");
            sprintf(messageString, "Received: ");
            sPrintBufferHex(messageString, rBufferMax, pbRecvBuffer);
            readersLogMessage(LOG_INFO, 3, messageString);
#endif
        }
        else
            *dwRecvLength = 0;
    }

    return(rv);

}