diff --git a/nfc/NfcCx/Cx/NfcCxRF.cpp b/nfc/NfcCx/Cx/NfcCxRF.cpp index 4160ea5..f4fb0a0 100644 --- a/nfc/NfcCx/Cx/NfcCxRF.cpp +++ b/nfc/NfcCx/Cx/NfcCxRF.cpp @@ -143,58 +143,80 @@ NfcCxRFInterfaceGetSEEvent( VOID FORCEINLINE NfcCxRFInterfaceClearRemoteDevList( _Inout_ PNFCCX_RF_INTERFACE RFInterface - ) +) { - if (RFInterface->pLibNfcContext->pRemDevList != NULL) { - if (RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo != NULL) { - if ((RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_A_PCD) || - (RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_B_PCD)) { - RFInterface->pLibNfcContext->bIsHCEConnected = FALSE; - } - free(RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo); - RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo = NULL; - } + if (RFInterface->pLibNfcContext->pRemDevList != NULL) + { + for (uint8_t bIndex = 0; bIndex < RFInterface->pLibNfcContext->uNoRemoteDevices; bIndex++) + { + if (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo != NULL) + { + if ((RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_A_PCD) || + (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_B_PCD)) + { + RFInterface->pLibNfcContext->bIsHCEConnected = FALSE; + } + free(RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo); + RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo = NULL; + } + } free(RFInterface->pLibNfcContext->pRemDevList); RFInterface->pLibNfcContext->pRemDevList = NULL; } + } + NTSTATUS FORCEINLINE NfcCxRFInterfaceSetRemoteDevList( _Inout_ PNFCCX_RF_INTERFACE RFInterface, - _In_ phLibNfc_RemoteDevList_t *psRemoteDevList + _In_ phLibNfc_RemoteDevList_t *psRemoteDevList, + _In_ uint8_t uNofRemoteDev ) { NTSTATUS status = STATUS_SUCCESS; + RFInterface->pLibNfcContext->SelectedProtocolIndex = 0; + NfcCxRFInterfaceClearRemoteDevList(RFInterface); - RFInterface->pLibNfcContext->pRemDevList = (phLibNfc_RemoteDevList_t*) malloc(sizeof(phLibNfc_RemoteDevList_t)); - if (RFInterface->pLibNfcContext->pRemDevList != NULL) { - RFInterface->pLibNfcContext->pRemDevList->hTargetDev = psRemoteDevList->hTargetDev; - RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo = - (phLibNfc_sRemoteDevInformation_t*) malloc(sizeof(phLibNfc_sRemoteDevInformation_t)); + RFInterface->pLibNfcContext->uNoRemoteDevices = uNofRemoteDev; - if (RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo != NULL) { - RtlCopyMemory(RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo, - psRemoteDevList->psRemoteDevInfo, sizeof(phLibNfc_sRemoteDevInformation_t)); + RFInterface->pLibNfcContext->pRemDevList = (phLibNfc_RemoteDevList_t*)malloc(sizeof(phLibNfc_RemoteDevList_t) * uNofRemoteDev); + if (RFInterface->pLibNfcContext->pRemDevList != NULL) + { - if ((RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_A_PCD) || - (RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_B_PCD)) { - RFInterface->pLibNfcContext->bIsHCEConnected = TRUE; + for (uint8_t bIndex = 0; bIndex < uNofRemoteDev; bIndex++) + { + RFInterface->pLibNfcContext->pRemDevList[bIndex].hTargetDev = psRemoteDevList[bIndex].hTargetDev; + RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo = + (phLibNfc_sRemoteDevInformation_t*)malloc(sizeof(phLibNfc_sRemoteDevInformation_t)); + + if (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo != NULL) + { + RtlCopyMemory(RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo, + psRemoteDevList[bIndex].psRemoteDevInfo, sizeof(phLibNfc_sRemoteDevInformation_t)); + + if ((RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_A_PCD) || + (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo->RemDevType == phLibNfc_eISO14443_B_PCD)) + { + RFInterface->pLibNfcContext->bIsHCEConnected = TRUE; + } + } + else + { + status = STATUS_INSUFFICIENT_RESOURCES; + NfcCxRFInterfaceClearRemoteDevList(RFInterface); + break; } } - else { - status = STATUS_INSUFFICIENT_RESOURCES; - NfcCxRFInterfaceClearRemoteDevList(RFInterface); - } } - else { + else + { status = STATUS_INSUFFICIENT_RESOURCES; - NfcCxRFInterfaceClearRemoteDevList(RFInterface); + RFInterface->pLibNfcContext->pRemDevList = NULL; } - return status; } @@ -1262,6 +1284,89 @@ Done: return status; } +NTSTATUS +NfcCxRFInterfaceTargetDeactivate( + _In_ PNFCCX_RF_INTERFACE RFInterface +) +/*++ + +Routine Description: + +This routine is called from the SC module to +reactivate a tag. + +Arguments: + +RFInterface - The RF Interface + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + WdfWaitLockAcquire(RFInterface->DeviceLock, NULL); + ResetEvent(RFInterface->hStartPresenceCheck); + + status = NfcCxRFInterfaceExecute(RFInterface, LIBNFC_TARGET_DEACTIVATE_SLEEP, NULL, NULL); + + if (!NT_SUCCESS(status)) { + TRACE_LINE(LEVEL_ERROR, "Target deactivation failed, %!STATUS!", status); + SetEvent(RFInterface->hStartPresenceCheck); + goto Done; + } + +Done: + WdfWaitLockRelease(RFInterface->DeviceLock); + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + return status; +} + +NTSTATUS +NfcCxRFInterfaceTargetActivate( + _In_ PNFCCX_RF_INTERFACE RFInterface +) +/*++ + +Routine Description: + +This routine is called from the SC module to +reactivate a tag. + +Arguments: + +RFInterface - The RF Interface + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + WdfWaitLockAcquire(RFInterface->DeviceLock, NULL); + + status = NfcCxRFInterfaceExecute(RFInterface, LIBNFC_TARGET_ACTIVATE, NULL, NULL); + + if (!NT_SUCCESS(status)) { + TRACE_LINE(LEVEL_ERROR, "Target Activation failed, %!STATUS!", status); + } + SetEvent(RFInterface->hStartPresenceCheck); + + WdfWaitLockRelease(RFInterface->DeviceLock); + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + return status; +} + NTSTATUS NfcCxRFInterfaceTargetCheckPresence( _In_ PNFCCX_RF_INTERFACE RFInterface @@ -1671,7 +1776,7 @@ NfcCxRFInterfaceTagConnectionEstablished( RFInterface->pLibNfcContext->bIsTagConnected = TRUE; NfcCxNfpInterfaceHandleTagConnectionEstablished(NfcCxRFInterfaceGetNfpInterface(RFInterface), ArrivalBitMask); NfcCxSCInterfaceHandleSmartCardConnectionEstablished(NfcCxRFInterfaceGetScInterface(RFInterface), - RFInterface->pLibNfcContext->pRemDevList->psRemoteDevInfo); + RFInterface); } TRACE_FUNCTION_EXIT(LEVEL_VERBOSE); @@ -2237,12 +2342,22 @@ NfcCxRFInterfaceRemoteDevConnect( LibNfcContext.RFInterface = RFInterface; LibNfcContext.Sequence = RFInterface->pSeqHandler; - nfcStatus = phLibNfc_RemoteDev_Connect(RFInterface->pLibNfcContext->pRemDevList[0].hTargetDev, + nfcStatus = phLibNfc_RemoteDev_Connect(RFInterface->pLibNfcContext->pRemDevList[RFInterface->pLibNfcContext->SelectedProtocolIndex].hTargetDev, NfcCxRFInterfaceRemoteDevConnectCB, &LibNfcContext); Status = NfcCxNtStatusFromNfcStatus(nfcStatus); + if (NT_SUCCESS(Status)) + { + TRACE_LINE(LEVEL_INFO, "Set Target Activation To %x", RFInterface->pLibNfcContext->SelectedProtocolIndex); + } + else + { + TRACE_LINE(LEVEL_INFO, "Set Target Activation Failed for Index %x", RFInterface->pLibNfcContext->SelectedProtocolIndex); + } + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status); return Status; } @@ -2283,7 +2398,7 @@ NfcCxRFInterfaceRemoteDevDisconnect( LibNfcContext.RFInterface = RFInterface; LibNfcContext.Sequence = RFInterface->pSeqHandler; - nfcStatus = phLibNfc_RemoteDev_Disconnect(RFInterface->pLibNfcContext->pRemDevList->hTargetDev, + nfcStatus = phLibNfc_RemoteDev_Disconnect(RFInterface->pLibNfcContext->pRemDevList[RFInterface->pLibNfcContext->SelectedProtocolIndex].hTargetDev, RFInterface->pLibNfcContext->eReleaseType, NfcCxRFInterfaceRemoteDevDisconnectCB, &LibNfcContext); @@ -2292,6 +2407,15 @@ NfcCxRFInterfaceRemoteDevDisconnect( nfcStatus = NFCSTATUS_SUCCESS; } + if (NT_SUCCESS(Status)) + { + TRACE_LINE(LEVEL_INFO, "Set Target DeActivation To %x", RFInterface->pLibNfcContext->SelectedProtocolIndex); + } + else + { + TRACE_LINE(LEVEL_INFO, "Set Target DeActivation Failed for Index %x", RFInterface->pLibNfcContext->SelectedProtocolIndex); + } + Status = NfcCxNtStatusFromNfcStatus(nfcStatus); TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, Status); @@ -2835,8 +2959,13 @@ NfcCxRFInterfaceTargetTransceive( NFCSTATUS nfcStatus = NFCSTATUS_SUCCESS; phLibNfc_RemoteDevList_t* pRemDevList = RFInterface->pLibNfcContext->pRemDevList; static NFCCX_RF_LIBNFC_REQUEST_CONTEXT LibNfcContext; + DWORD SelectedProtocol = 0; - switch (pRemDevList->psRemoteDevInfo->RemDevType) + SelectedProtocol = RFInterface->pLibNfcContext->SelectedProtocolIndex; + + TRACE_LINE(LEVEL_INFO, "SelectedProtocol is = %x", SelectedProtocol); + + switch (pRemDevList[SelectedProtocol].psRemoteDevInfo->RemDevType) { case phLibNfc_eISO14443_4A_PICC: case phLibNfc_eISO14443_4B_PICC: @@ -2892,7 +3021,7 @@ NfcCxRFInterfaceTargetTransceive( LibNfcContext.RFInterface = RFInterface; LibNfcContext.Sequence = RFInterface->pSeqHandler; - nfcStatus = phLibNfc_RemoteDev_Transceive(pRemDevList->hTargetDev, + nfcStatus = phLibNfc_RemoteDev_Transceive(RFInterface->pLibNfcContext->pRemDevList[SelectedProtocol].hTargetDev, &RFInterface->sTransceiveBuffer, NfcCxRFInterfaceTargetTransceiveCB, &LibNfcContext); @@ -2935,7 +3064,7 @@ NfcCxRFInterfaceTargetPresenceCheck( LibNfcContext.RFInterface = RFInterface; LibNfcContext.Sequence = RFInterface->pSeqHandler; - nfcStatus = phLibNfc_RemoteDev_CheckPresence(RFInterface->pLibNfcContext->pRemDevList->hTargetDev, + nfcStatus = phLibNfc_RemoteDev_CheckPresence(RFInterface->pLibNfcContext->pRemDevList[RFInterface->pLibNfcContext->SelectedProtocolIndex].hTargetDev, NfcCxRFInterfaceTargetPresenceCheckCB, &LibNfcContext); @@ -2945,6 +3074,7 @@ NfcCxRFInterfaceTargetPresenceCheck( return Status; } + NTSTATUS NfcCxRFInterfaceSENtfRegister( _In_ PNFCCX_RF_INTERFACE RFInterface, @@ -3388,7 +3518,7 @@ NfcCxRFInterfaceRemoteDevNtfCB( TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), TraceLoggingValue((DWORD)(psRemoteDev->psRemoteDevInfo->RemDevType), "DeviceType")); - status = NfcCxRFInterfaceSetRemoteDevList(rfInterface, psRemoteDev); + status = NfcCxRFInterfaceSetRemoteDevList(rfInterface, psRemoteDev, uNofRemoteDev); if (NT_SUCCESS(status)) { NfcCxStateInterfaceStateHandler(NfcCxRFInterfaceGetStateInterface(rfInterface), NfcCxEventDiscovered, NULL, NULL, NULL); diff --git a/nfc/NfcCx/Cx/NfcCxRF.h b/nfc/NfcCx/Cx/NfcCxRF.h index 17ca7a5..b3f557f 100644 --- a/nfc/NfcCx/Cx/NfcCxRF.h +++ b/nfc/NfcCx/Cx/NfcCxRF.h @@ -69,6 +69,8 @@ typedef struct _NFCCX_LIBNFC_CONTEXT { BOOLEAN bIsTagWriteAttempted; BOOLEAN bIsTagReadOnlyAttempted; BOOLEAN bIsP2PConnected; + uint8_t uNoRemoteDevices; + DWORD SelectedProtocolIndex; phLibNfc_eReleaseType_t eReleaseType; PNFCCX_STATE_INTERFACE StateInterface; PNFCCX_LLCP_INTERFACE LLCPInterface; @@ -287,6 +289,16 @@ NfcCxRFInterfaceTargetReactivate( _In_ PNFCCX_RF_INTERFACE RFInterface ); +NTSTATUS +NfcCxRFInterfaceTargetDeactivate( + _In_ PNFCCX_RF_INTERFACE RFInterface +); + +NTSTATUS +NfcCxRFInterfaceTargetActivate( + _In_ PNFCCX_RF_INTERFACE RFInterface + ); + NTSTATUS NfcCxRFInterfaceGetSecureElementList( _In_ PNFCCX_RF_INTERFACE RFInterface, diff --git a/nfc/NfcCx/Cx/NfcCxSC.cpp b/nfc/NfcCx/Cx/NfcCxSC.cpp index 29d42a3..c96efe9 100644 --- a/nfc/NfcCx/Cx/NfcCxSC.cpp +++ b/nfc/NfcCx/Cx/NfcCxSC.cpp @@ -907,7 +907,7 @@ Done: VOID NfcCxSCInterfaceHandleSmartCardConnectionEstablished( _In_ PNFCCX_SC_INTERFACE ScInterface, - _In_ phNfc_sRemoteDevInformation_t* pRemoteDeviceInfo + _In_ PNFCCX_RF_INTERFACE RFInterface ) /*++ @@ -927,9 +927,20 @@ Return Value: --*/ { NTSTATUS status = STATUS_SUCCESS; + DWORD DefaultProtocol = RFInterface->pLibNfcContext->SelectedProtocolIndex; + phNfc_sRemoteDevInformation_t* pRemoteDeviceInfo = NULL; TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + WdfWaitLockAcquire(ScInterface->SmartCardLock, NULL); + + ScInterface->SmartCardConnected = TRUE; + + TRACE_LINE(LEVEL_INFO, "SmartCardConnectionEstablished!!!"); + + pRemoteDeviceInfo = RFInterface->pLibNfcContext->pRemDevList[DefaultProtocol].psRemoteDevInfo; + RtlCopyMemory(&ScInterface->RemoteDeviceInfo, pRemoteDeviceInfo, sizeof(phNfc_sRemoteDevInformation_t)); + switch (pRemoteDeviceInfo->RemDevType) { case phLibNfc_eISO14443_4A_PICC: @@ -944,13 +955,6 @@ Return Value: TRACE_LINE(LEVEL_WARNING, "Unsupported SmartCard type %!phNfc_eRFDevType_t!", pRemoteDeviceInfo->RemDevType); goto Done; } - - TRACE_LINE(LEVEL_INFO, "SmartCardConnectionEstablished!!!"); - - WdfWaitLockAcquire(ScInterface->SmartCardLock, NULL); - - ScInterface->SmartCardConnected = TRUE; - RtlCopyMemory(&ScInterface->RemoteDeviceInfo, pRemoteDeviceInfo, sizeof(phNfc_sRemoteDevInformation_t)); status = NfcCxSCInterfaceLoadStorageClassFromAtrLocked(ScInterface); WdfWaitLockRelease(ScInterface->SmartCardLock); @@ -1098,8 +1102,9 @@ Return Value: DWORD *pdwAttributeId = (DWORD*)InputBuffer; size_t cbOutputBuffer = OutputBufferLength; PNFCCX_SC_INTERFACE scInterface; + PNFCCX_FDO_CONTEXT fdoContext; + - UNREFERENCED_PARAMETER(Request); UNREFERENCED_PARAMETER(InputBufferLength); TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); @@ -1109,9 +1114,23 @@ Return Value: // _Analysis_assume_(sizeof(BYTE) <= OutputBufferLength); + fdoContext = NfcCxFdoGetContext(Device); + scInterface = fdoContext->SCInterface; - scInterface = NfcCxFdoGetContext(Device)->SCInterface; + if ((*pdwAttributeId == SCARD_ATTR_VENDOR_SPECIFIC_BRAND_INFO) || (*pdwAttributeId == SCARD_ATTR_VENDOR_SPECIFIC_DEVICECAP_INFO)) + { + if (NULL != fdoContext->NfcCxClientGlobal->Config.EvtNfcCxDeviceIoControl) { + fdoContext->NfcCxClientGlobal->Config.EvtNfcCxDeviceIoControl(fdoContext->Device, + Request, + OutputBufferLength, + InputBufferLength, + IOCTL_SMARTCARD_GET_ATTRIBUTE); + status = STATUS_PENDING; + goto Done; + + } + } for (USHORT TableEntry = 0; TableEntry < ARRAYSIZE(g_ScAttributeDispatch); TableEntry++) { if (g_ScAttributeDispatch[TableEntry].dwAttributeId == *pdwAttributeId) { @@ -1144,7 +1163,7 @@ Return Value: // status = STATUS_PENDING; } - +Done: TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); TRACE_LOG_NTSTATUS_ON_FAILURE(status); @@ -1183,9 +1202,10 @@ Return Value: { NTSTATUS status = STATUS_NOT_SUPPORTED; DWORD *pdwAttributeId = (DWORD*)InputBuffer; + PNFCCX_FDO_CONTEXT fdoContext; UNREFERENCED_PARAMETER(Device); - UNREFERENCED_PARAMETER(Request); + UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBuffer); UNREFERENCED_PARAMETER(OutputBufferLength); @@ -1197,10 +1217,27 @@ Return Value: // _Analysis_assume_(sizeof(DWORD) <= InputBufferLength); + fdoContext = NfcCxFdoGetContext(Device); + + if (*pdwAttributeId == SCARD_ATTR_VENDOR_SPECIFIC_BRAND_INFO) + { + if (NULL != fdoContext->NfcCxClientGlobal->Config.EvtNfcCxDeviceIoControl) { + fdoContext->NfcCxClientGlobal->Config.EvtNfcCxDeviceIoControl(fdoContext->Device, + Request, + OutputBufferLength, + InputBufferLength, + IOCTL_SMARTCARD_SET_ATTRIBUTE); + status = STATUS_PENDING; + goto Done; + + } + } + + if (*pdwAttributeId == SCARD_ATTR_DEVICE_IN_USE) { status = STATUS_SUCCESS; } - +Done: TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); TRACE_LOG_NTSTATUS_ON_FAILURE(status); @@ -1718,6 +1755,49 @@ Return Value: cbOutputBufferUsed = cbResponseBuffer; } + else if (NfcCxSCInterfaceValidateSwitchProtocolCommand((PBYTE)InputBuffer + sizeof(SCARD_IO_REQUEST), + cbInputBuffer - sizeof(SCARD_IO_REQUEST)) == TRUE){ + BYTE Sw1Sw2[DEFAULT_APDU_STATUS_SIZE] = { 0x90,0x00 }; + + status = NfcCxSCInterfaceDeactivateMultiProtocolTag(scInterface); + if (NT_SUCCESS(status)){ + WdfWaitLockAcquire(scInterface->SmartCardLock, NULL); + + status = NfcCxSCInterfaceLoadNewSelectedProtocol( + scInterface, + (PBYTE)InputBuffer + sizeof(SCARD_IO_REQUEST), + cbInputBuffer - sizeof(SCARD_IO_REQUEST)); + + if (!NT_SUCCESS(status)) { + TRACE_LINE(LEVEL_ERROR, "Failed to Load new Select protocol, %!STATUS!", status); + } + // + // Irrespective of loaded index of selected protocol, tag activation is needed as tag + // Deactivation done before. + // + WdfWaitLockRelease(scInterface->SmartCardLock); + + status = NfcCxSCInterfaceActivateMultiProtocolTag(scInterface); + if (!NT_SUCCESS(status)){ + TRACE_LINE(LEVEL_ERROR, "Failed to Activate New protocol, %!STATUS!", status); + RtlCopyMemory(Sw1Sw2, APDU_STATUS_ERROR_COMMAND_ABORTED, DEFAULT_APDU_STATUS_SIZE); + } + } else { + TRACE_LINE(LEVEL_ERROR, "Failed to Deactivate current protocol, %!STATUS!", status); + RtlCopyMemory(Sw1Sw2, APDU_STATUS_ERROR_COMMAND_ABORTED, DEFAULT_APDU_STATUS_SIZE); + } + status = NfcCxSCInterfaceCopyResponseData(OutputBuffer, + cbOutputBuffer, + Sw1Sw2, + sizeof(Sw1Sw2), + &cbResponseBuffer); + if (!NT_SUCCESS(status)) { + TRACE_LINE(LEVEL_ERROR, "Failed to construct response buffer, %!STATUS!", status); + goto Done; + } + TRACE_LINE(LEVEL_ERROR, "smartcard resp 90 00 sending %d", cbResponseBuffer); + cbOutputBufferUsed = cbResponseBuffer; + } else { status = NfcCxSCInterfaceTransmitRequest(scInterface, (PBYTE)InputBuffer + sizeof(SCARD_IO_REQUEST), @@ -2834,6 +2914,116 @@ Done: return fLoadKey; } +BOOL NfcCxSCInterfaceValidateSwitchProtocolCommand( + _In_bytecount_(InputBufferLength) PBYTE InputBuffer, + _In_ DWORD InputBufferLength +) +{ + BOOL retval = FALSE; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + TRACE_LINE(LEVEL_INFO, "ValidateSwitchProtocolCommand Size = %x\n", InputBufferLength); + if (InputBufferLength < PCSC_SWITCH_PROTOCOL_APDU_SIZE) + { + TRACE_LINE(LEVEL_ERROR, "Invalid APDU buffer size"); + goto Done; + } + else + { + PPcscCommandApduInfo cmdApdu = (PPcscCommandApduInfo)InputBuffer; + if ((PCSC_CLASS_BYTE == cmdApdu->Cla) && + (PcscEnvelopeCmd == cmdApdu->Ins) && + (PCSC_PARA1_SWITCH_BYTE == cmdApdu->P1) && ((PCSC_PARA2_SWITCH_BYTE == cmdApdu->P2))) + { + TRACE_LINE(LEVEL_INFO,"Command APDU is Switch Protocol \n"); + retval = TRUE; + } + else + { + TRACE_LINE(LEVEL_INFO,"Command APDU is NOT Switch Protocol \n"); + } + } + +Done: + + TRACE_LINE(LEVEL_INFO,"%s (OUT) (return %d) \n", __FUNCTION__, retval); + return retval; +} + +NTSTATUS NfcCxSCInterfaceLoadNewSelectedProtocol( + _In_ PNFCCX_SC_INTERFACE ScInterface, + _In_bytecount_(InputBufferLength) PBYTE InputBuffer, + _In_ DWORD InputBufferLength +) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + PcscSwitchProtocolAPDU SelProtocolApdu; + DWORD SelectedProtocol = 0; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + memcpy(&SelProtocolApdu, InputBuffer, InputBufferLength); + + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbCLA = %x\n", SelProtocolApdu.pbCLA); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbINS = %x\n", SelProtocolApdu.pbINS); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbP1 = %x\n", SelProtocolApdu.pbP1); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbP2 = %x\n", SelProtocolApdu.pbP2); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbLc = %x\n", SelProtocolApdu.pbLc); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.TlvMsg.Type = %x\n", SelProtocolApdu.PcscSwitchProtoData.Tag); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.TlvMsg.Length = %x\n", SelProtocolApdu.PcscSwitchProtoData.Length); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.TlvMsg.value[0]= %x\n", SelProtocolApdu.PcscSwitchProtoData.value[0]); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.TlvMsg.value[1]= %x\n", SelProtocolApdu.PcscSwitchProtoData.value[1]); + TRACE_LINE(LEVEL_INFO, "\n SelProtocolApdu.pbLe = %x\n", SelProtocolApdu.pbLe); + + //Parse APDU and select the prefered protocol + + if (((SelProtocolApdu.PcscSwitchProtoData.value[0] == PCSC_SWITCH_PROTOCOL_STD_TYPE) && (SelProtocolApdu.PcscSwitchProtoData.value[1] == PCSC_SELECT_PROTOCOL_MIFARE)) || + ((SelProtocolApdu.PcscSwitchProtoData.value[0] == PCSC_SWITCH_PROTOCOL_STD_TYPE) && (SelProtocolApdu.PcscSwitchProtoData.value[1] == PCSC_SELECT_PROTOCOL_ISO4A))) + { + if (PCSC_SELECT_PROTOCOL_ISO4A == SelProtocolApdu.PcscSwitchProtoData.value[1]) + { + //Find 4A devinfo from the RemoteDeviceList return index + SelectedProtocol = NfcCxSCInterfaceGetIndexOfProtocolType(ScInterface->FdoContext->RFInterface, phNfc_eISO14443_4A_PICC); + if (PCSC_SWITCH_PROTOCOL_INDEX_NOT_FOUND != SelectedProtocol) + { + TRACE_LINE(LEVEL_INFO, "\n Selected protocol is 4A at index %d \n", SelectedProtocol); + status = STATUS_SUCCESS; + } + else + { + TRACE_LINE(LEVEL_INFO, "\n Selected protocol is 4A not found "); + goto Done; + } + } + if (PCSC_SELECT_PROTOCOL_MIFARE == SelProtocolApdu.PcscSwitchProtoData.value[1]) + { + //Find mifare devinfo from the RemoteDeviceList return index + SelectedProtocol = NfcCxSCInterfaceGetIndexOfProtocolType(ScInterface->FdoContext->RFInterface, phNfc_eMifare_PICC); + if (PCSC_SWITCH_PROTOCOL_INDEX_NOT_FOUND != SelectedProtocol) + { + TRACE_LINE(LEVEL_INFO, "\n Selected protocol is Mifare at index %d \n", SelectedProtocol); + status = STATUS_SUCCESS; + } + else + { + TRACE_LINE(LEVEL_INFO, "\n Selected protocol is Mifare not found "); + goto Done; + } + } + ScInterface->FdoContext->RFInterface->pLibNfcContext->SelectedProtocolIndex = SelectedProtocol; + } + + RtlCopyMemory(&ScInterface->RemoteDeviceInfo, ScInterface->FdoContext->RFInterface->pLibNfcContext->pRemDevList[SelectedProtocol].psRemoteDevInfo, sizeof(phNfc_sRemoteDevInformation_t)); + + NfcCxSCInterfaceLoadStorageClassFromAtrLocked(ScInterface); + +Done: + + TRACE_LINE(LEVEL_INFO, "%s (OUT) (return %d) \n", __FUNCTION__, status); + return status; +} + _Requires_lock_held_(ScInterface->SmartCardLock) NTSTATUS NfcCxSCInterfaceLoadKeyLocked( @@ -3669,3 +3859,136 @@ Routine Description: return tck; } + +BOOLEAN +NfcCxSCInterfaceIsMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface +) +/*++ + +Routine Description: + +This routine checks wheather smart card tag is multiprotocol Tag + +--*/ +{ + BOOLEAN fResult = FALSE; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + NT_ASSERT(ScInterface->SmartCardConnected); + + if (ScInterface->FdoContext->RFInterface->pLibNfcContext != NULL) + { + if (ScInterface->FdoContext->RFInterface->pLibNfcContext->uNoRemoteDevices > 1) + { + fResult = TRUE; + } + } + + TRACE_FUNCTION_EXIT(LEVEL_VERBOSE); + + return fResult; +} + +_Requires_lock_not_held_(ScInterface->SmartCardLock) +NTSTATUS +NfcCxSCInterfaceDeactivateMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface +) +/*++ + +Routine Description: + +This routine DeActivates the smart card + +Arguments: + +ScInterface - The SC Interface + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + TRACE_LINE(LEVEL_INFO, "Card DeactivateCommand Sent"); + + status = NfcCxRFInterfaceTargetDeactivate(ScInterface->FdoContext->RFInterface); + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + + return status; +} + +_Requires_lock_not_held_(ScInterface->SmartCardLock) +NTSTATUS +NfcCxSCInterfaceActivateMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface +) +/*++ + +Routine Description: + +This routine Activates the smart card + +Arguments: + +ScInterface - The SC Interface + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + TRACE_LINE(LEVEL_INFO, "Card ActivateCommand Sent"); + + status = NfcCxRFInterfaceTargetActivate(ScInterface->FdoContext->RFInterface); + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + + return status; +} + +DWORD +NfcCxSCInterfaceGetIndexOfProtocolType( + _Inout_ PNFCCX_RF_INTERFACE RFInterface, + _In_ phNfc_eRemDevType_t RemDevType +) +{ + DWORD bIndex = 0x00; + DWORD SelectedProtocolIndex = PCSC_SWITCH_PROTOCOL_INDEX_NOT_FOUND; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + if (RFInterface->pLibNfcContext->pRemDevList != NULL) + { + for (bIndex = 0; bIndex < RFInterface->pLibNfcContext->uNoRemoteDevices; bIndex++) + { + if (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo != NULL) + { + if (RFInterface->pLibNfcContext->pRemDevList[bIndex].psRemoteDevInfo->RemDevType == RemDevType) + { + SelectedProtocolIndex = bIndex; + } + else + { + TRACE_LINE(LEVEL_ERROR, "Specified Protocol not found in the list"); + } + } + } + } + + TRACE_FUNCTION_EXIT(LEVEL_VERBOSE); + + return SelectedProtocolIndex; +} diff --git a/nfc/NfcCx/Cx/NfcCxSC.h b/nfc/NfcCx/Cx/NfcCxSC.h index 2e00e35..3305b31 100644 --- a/nfc/NfcCx/Cx/NfcCxSC.h +++ b/nfc/NfcCx/Cx/NfcCxSC.h @@ -18,6 +18,10 @@ Environment: #pragma once +// To be removed once these Attribute IDs are defined in winsmcrd.h +#define SCARD_ATTR_VENDOR_SPECIFIC_BRAND_INFO 0x0180 +#define SCARD_ATTR_VENDOR_SPECIFIC_DEVICECAP_INFO 0x0181 + #define HINIBBLE(b) ((BYTE)((b >> 4) & 0x0f)) #define LONIBBLE(b) ((BYTE)(b & 0x0f)) @@ -28,6 +32,7 @@ Environment: #define APDU_STATUS_ERROR_DATA_OBJECT_MISSING "\x69\x87" #define APDU_STATUS_ERROR_INCORRECT_DATA_OBJECT "\x69\x88" #define APDU_STATUS_ERROR_INVALID_OBJECT_LENGTH "\x69\x89" +#define APDU_STATUS_ERROR_COMMAND_ABORTED "\x6F\x00" #define APDU_STATUS_SUCCESS "\x90\x00" #define SAK_MIFARE_UL 0x00 @@ -87,6 +92,14 @@ Environment: #define MIFARE_UL_AUTHENTICATE_RESPONSE_BUFFER_SIZE 9 #define MIFARE_UL_AUTHENTICATE_RESPONSE_TIMEOUT 100 +#define PCSC_SELECT_PROTOCOL_MIFARE 0x03 +#define PCSC_SELECT_PROTOCOL_ISO4A 0x04 +#define PCSC_SWITCH_PROTOCOL_TYPE 0X8F +#define PCSC_SWITCH_PROTOCOL_LENGTH 0X02 +#define PCSC_SWITCH_PROTOCOL_STD_TYPE 0X00 +#define PCSC_SWITCH_PROTOCOL_APDU_SIZE 0x09 +#define PCSC_SWITCH_PROTOCOL_INDEX_NOT_FOUND 0xFF + typedef NTSTATUS NFCCX_SC_DISPATCH_HANDLER( @@ -154,6 +167,10 @@ typedef struct _NFCCX_SC_INTERFACE { _Guarded_by_(SmartCardLock) phNfc_sRemoteDevInformation_t RemoteDeviceInfo; + // + // Selected DeviceInfo Number from DeviceList + // + DWORD SelectedProtocolIndex; // // SmartCard storage card reference counted pointer // @@ -218,7 +235,7 @@ NfcCxSCInterfaceRemoveClient( VOID NfcCxSCInterfaceHandleSmartCardConnectionEstablished( _In_ PNFCCX_SC_INTERFACE ScInterface, - _In_ phNfc_sRemoteDevInformation_t* pRemoteDeviceInfo + _In_ PNFCCX_RF_INTERFACE RFInterface ); VOID @@ -353,6 +370,12 @@ NfcCxSCInterfaceValidateLoadKeyCommand( _In_ DWORD InputBufferLength ); +BOOL +NfcCxSCInterfaceValidateSwitchProtocolCommand( + _In_bytecount_(InputBufferLength) PBYTE InputBuffer, + _In_ DWORD InputBufferLength + ); + NTSTATUS NfcCxSCInterfaceValidateMifareLoadKeyParameters( _In_bytecount_(InputBufferLength) PBYTE InputBuffer, @@ -460,12 +483,48 @@ NfcCxSCInterfaceResetCard( _In_ PNFCCX_SC_INTERFACE ScInterface ); +_Requires_lock_not_held_(ScInterface->SmartCardLock) +BOOLEAN +NfcCxSCInterfaceDetectMifareULC( + _In_ PNFCCX_SC_INTERFACE ScInterface + ); + +_Requires_lock_not_held_(ScInterface->SmartCardLock) +NTSTATUS +NfcCxSCInterfaceDeactivateMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface +); + +_Requires_lock_not_held_(ScInterface->SmartCardLock) +NTSTATUS +NfcCxSCInterfaceActivateMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface +); + BYTE NfcCxSCInterfaceComputeChecksum( _In_reads_bytes_(cbAtr) BYTE* pAtr, _In_ DWORD cbAtr ); +BOOLEAN +NfcCxSCInterfaceIsMultiProtocolTag( + _In_ PNFCCX_SC_INTERFACE ScInterface + ); + +NTSTATUS +NfcCxSCInterfaceLoadNewSelectedProtocol( + _In_ PNFCCX_SC_INTERFACE ScInterface, + _In_bytecount_(InputBufferLength) PBYTE InputBuffer, + _In_ DWORD InputBufferLength +); + +DWORD +NfcCxSCInterfaceGetIndexOfProtocolType( + _Inout_ PNFCCX_RF_INTERFACE RFInterface, + _In_ phNfc_eRemDevType_t RemDevType +); + // // Inline helper functions // diff --git a/nfc/NfcCx/Cx/driver.cpp b/nfc/NfcCx/Cx/driver.cpp index deb6876..6ef44cf 100644 --- a/nfc/NfcCx/Cx/driver.cpp +++ b/nfc/NfcCx/Cx/driver.cpp @@ -1059,6 +1059,8 @@ NfcCxBindClient( (PFN_NFC_CX)NfcCxEvtSetLlcpConfig, (PFN_NFC_CX)NfcCxEvtRegisterSequenceHandler, (PFN_NFC_CX)NfcCxEvtUnregisterSequenceHandler, + (PFN_NFC_CX)NfcCxEvtReleaseHardwareControl, + (PFN_NFC_CX)NfcCxEvtReacquireHardwareControl, }; TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); @@ -1132,3 +1134,108 @@ NfcCxUnbindClient( Done: TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); } + +NTSTATUS +NfcCxEvtReleaseHardwareControl( + _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + +This routine is called by the CX client to make CX driver +release the NFCC access. + +Arguments: + +Device - WDF device to initialize + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PNFCCX_FDO_CONTEXT fdoContext; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + if (!VerifyPrivateGlobals(NfcCxGlobals)) { + TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer"); + status = STATUS_INVALID_PARAMETER; + goto Done; + } + + fdoContext = NfcCxFdoGetContext(Device); + + if (fdoContext->RFInterface == NULL) { + TRACE_LINE(LEVEL_ERROR, "CX not initialized"); + status = STATUS_INVALID_DEVICE_STATE; + goto Done; + } + + status = NfcCxFdoDeInitialize(fdoContext); + +Done: + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + return status; +} + +NTSTATUS +NfcCxEvtReacquireHardwareControl( + _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, + _In_ WDFDEVICE Device +) +/*++ + +Routine Description: + +This routine is called by the CX client to make CX driver +reacquire the NFCC access. + +Arguments: + +Device - WDF device to initialize + +Return Value: + +NTSTATUS + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PNFCCX_FDO_CONTEXT fdoContext; + + TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); + + if (!VerifyPrivateGlobals(NfcCxGlobals)) { + TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer"); + status = STATUS_INVALID_PARAMETER; + goto Done; + } + fdoContext = NfcCxFdoGetContext(Device); + + if (fdoContext->RFInterface == NULL) { + TRACE_LINE(LEVEL_ERROR, "CX not initialized"); + status = STATUS_INVALID_DEVICE_STATE; + goto Done; + } + + status = NfcCxFdoInitialize(fdoContext); + if (STATUS_SUCCESS == status) + { + status = NfcCxRFInterfaceUpdateDiscoveryState(fdoContext->RFInterface); + } + else + { + TRACE_LINE(LEVEL_ERROR, "Failed to initialize the Fdo, %!STATUS!", status); + } + +Done: + + TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); + return status; +} \ No newline at end of file diff --git a/nfc/NfcCx/Cx/driver.h b/nfc/NfcCx/Cx/driver.h index b30927c..131c327 100644 --- a/nfc/NfcCx/Cx/driver.h +++ b/nfc/NfcCx/Cx/driver.h @@ -158,4 +158,16 @@ NfcCxEvtUnregisterSequenceHandler( _In_ NFC_CX_SEQUENCE Sequence ); +NTSTATUS +NfcCxEvtReleaseHardwareControl( + _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, + _In_ WDFDEVICE Device +); + +NTSTATUS +NfcCxEvtReacquireHardwareControl( + _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, + _In_ WDFDEVICE Device +); + WDF_EXTERN_C_END diff --git a/nfc/libs/SmartCard/inc/StorageClass.h b/nfc/libs/SmartCard/inc/StorageClass.h index db50a81..138c8ac 100644 --- a/nfc/libs/SmartCard/inc/StorageClass.h +++ b/nfc/libs/SmartCard/inc/StorageClass.h @@ -28,6 +28,10 @@ Environment: #define COMMAND_BUFFER_SIZE 512 #define DEFAULT_APDU_STATUS_SIZE 2 +#define PCSC_CLASS_BYTE 0xFF +#define PCSC_PARA1_SWITCH_BYTE 0x00 +#define PCSC_PARA2_SWITCH_BYTE 0x02 + enum ApduResult { RESULT_SUCCESS, @@ -133,6 +137,25 @@ typedef enum _PcscIncrementDecrement BlkValueCmd = 0x81, } PcscIncrementDecrement; + +typedef struct _PcscSwitchProtocolDataObject +{ + unsigned char Tag; // 0x8F + unsigned char Length; // 0x02 + unsigned char value[2]; // For values see spec +}SwitchProtocolTlv_t; + +typedef struct _PcscSwitchProtocolAPDU +{ + unsigned char pbCLA; // 0xFF + unsigned char pbINS; // 0xC2 + unsigned char pbP1; // 0x00 + unsigned char pbP2; // 0x00 + unsigned char pbLc; // 0x02 + _PcscSwitchProtocolDataObject PcscSwitchProtoData; + unsigned char pbLe; +}PcscSwitchProtocolAPDU; + class IStorageCard { public: