public static ApduOperationResult IsApduSuccessful(ApduResponse response) { var baseOperationResult = GetErrorMessage(response.ReturnCode); var apduOperationStatus = Check90_00(response.RecvBuff, response.ResponseLength); return(new ApduOperationResult(baseOperationResult, apduOperationStatus)); }
private static TLVList ReadAllPSERecords(TLV sfi, CardQProcessor cardInterfaceManager) { byte record = 1; TLVList _61 = new TLVList(); while (record != 0) { EMVReadRecordRequest request = new EMVReadRecordRequest(sfi.Value[0], record); //do read record commands starting with record 1 untill the card returns 6A83 ApduResponse cardResponse = cardInterfaceManager.SendCommand(request); if (cardResponse is EMVReadRecordResponse) { if (cardResponse.Succeeded) { TLVList tags = (cardResponse as EMVReadRecordResponse).GetResponseTags(); foreach (TLV tlv in tags) { _61.AddToList(tlv, true); } record++; } else { record = 0; } } else { throw new EMVProtocolException("ReadAllRecords transmit error"); } } return(_61); }
SelectAppChosen(CardQProcessor cardInterfaceManager, TerminalSupportedKernelAidTransactionTypeCombination supportedKernelAidCombination, CardKernelAidCombination candidate) { string finalAdfName = Formatting.ByteArrayToHexString(candidate.AdfNameTag.Value); ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName)) as EMVSelectApplicationResponse; EMVSelectApplicationResponse response; if (cardResponse is EMVSelectApplicationResponse) { response = (EMVSelectApplicationResponse)cardResponse; } else { throw new EMVProtocolException("Pre-processing transmit error: try again"); } if (!response.Succeeded) { return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.CombinationSelection_StartC }, response, supportedKernelAidCombination)); } //TLV ttqInPDOL = response.GetPDOLTags().Get(EMVTagsEnum.TERMINAL_TRANSACTION_QUALIFIERS_TTQ_9F66_KRN.Tag); return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.KernelActivation_StartD }, response, supportedKernelAidCombination)); }
/// <summary> /// Returns a card's UID. /// </summary> public ReceiveCardIdResult GetCardId(Card cardToRead) { if (cardToRead == null) { throw new ArgumentNullException("cardToRead"); } var bytesToSend = new byte[5]; bytesToSend[0] = 0xFF; // Class bytesToSend[1] = 0xCA; // INS bytesToSend[2] = 0x00; // P1 bytesToSend[3] = 0x00; // P2 bytesToSend[4] = 0x00; // LE:Full Length ApduResponse response = SendAPDU(cardToRead, bytesToSend, 10); const int responseCodeLength = 2; var responseLengthWithoutResponseCodes = response.ResponseLength - responseCodeLength; var receiveCardIdResult = new ReceiveCardIdResult(ReturnCodeManager.IsApduSuccessful(response)); if (receiveCardIdResult.IsCompletelySuccessful) { //read UID bytes from apdu response receiveCardIdResult.Bytes = response.RecvBuff.Take(responseLengthWithoutResponseCodes).ToArray(); } return(receiveCardIdResult); }
private ApduResponse SendCommand(ApduCommand apduCommand) { ApduResponse response = cardInterface.SendCommand(apduCommand); if (response is DesfireResponse) { return(response); } throw new DesFireException("Error returned from card"); }
private EMVResponse SendCommand(EMVCommand apduCommand) { ApduResponse response = cardInterface.SendCommand(apduCommand); if (response is EMVResponse) { return((EMVResponse)response); } throw new PersoException("Error returned from card"); }
public Task <KeyResponse <KeyRegisterResponse> > RegisterAsync(KeyRegisterRequest request, CancellationToken cancellationToken = new CancellationToken(), bool invididualAttestation = false) { if (request == null) { throw new ArgumentNullException(nameof(request)); } log.Info(">> register"); var applicationSha256 = request.ApplicationSha256; var challengeSha256 = request.ChallengeSha256; log.Info(" -- Inputs --"); log.Info(" applicationSha256: " + applicationSha256.ToHexString()); log.Info(" challengeSha256: " + challengeSha256.ToHexString()); var userPresent = userPresenceVerifier.VerifyUserPresence(); if ((userPresent & UserPresenceVerifierConstants.UserPresentFlag) == 0) { return(TestOfUserPresenceRequired <KeyRegisterResponse>()); } var keyPair = keyPairGenerator.GenerateKeyPair(applicationSha256, challengeSha256); var keyHandle = keyHandleGenerator.GenerateKeyHandle(applicationSha256, keyPair); dataStore.StoreKeyPair(keyHandle, keyPair); var userPublicKey = keyPairGenerator.EncodePublicKey(keyPair.PublicKey); var signedData = RawMessageCodec.EncodeKeyRegisterSignedBytes(applicationSha256, challengeSha256, keyHandle, userPublicKey); log.Info("Signing bytes " + signedData.ToHexString()); var signature = crypto.Sign(signedData, certificatePrivateKey); log.Info(" -- Outputs --"); log.Info(" userPublicKey: " + userPublicKey.ToHexString()); log.Info(" keyHandle: " + keyHandle.ToHexString()); log.Info(" vendorCertificate: " + vendorCertificate); log.Info(" signature: " + signature.ToHexString()); log.Info("<< register"); var response = new KeyRegisterResponse(userPublicKey, keyHandle, vendorCertificate, signature); var responseData = RawMessageCodec.EncodeKeyRegisterResponse(response).Segment(); var apdu = new ApduResponse(ApduResponseStatus.NoError, responseData); var keyResponse = new KeyResponse <KeyRegisterResponse>(apdu, response, KeyResponseStatus.Success); return(TaskEx.FromResult(keyResponse)); }
private static EMVSelectPPSEResponse SelectPSEApplication(CardQProcessor cardInterfaceManager) { //same as contactless except for name ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectPPSERequest("1PAY.SYS.DDF01")); if (cardResponse is EMVSelectPPSEResponse) { return((EMVSelectPPSEResponse)cardResponse); } else { throw new EMVProtocolException("Pre-processing transmit error: try again"); } }
private static EMVSelectPPSEResponse FinalCombinationSelection_Step1(CardQProcessor cardInterfaceManager) { //Step 1 //3.3.2.2 ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectPPSERequest("2PAY.SYS.DDF01")); if (cardResponse is EMVSelectPPSEResponse) { return((EMVSelectPPSEResponse)cardResponse); } else { throw new EMVProtocolException("Pre-processing transmit error: try again"); } }
public ApduOperationResult SetBuzzerOutputForCardDetection(Card card, bool shouldBuzzWhenCardDetected) { var bytesToSend = new byte[5]; bytesToSend[0] = 0xFF; bytesToSend[1] = 0x00; bytesToSend[2] = 0x52; bytesToSend[3] = shouldBuzzWhenCardDetected ? (byte)0xFF : (byte)0x00; bytesToSend[4] = 0x00; const int responseCodeLength = 2; ApduResponse response = SendAPDU(card, bytesToSend, responseCodeLength); return(ReturnCodeManager.IsApduSuccessful(response)); }
public Task <KeyResponse <KeySignResponse> > SignAsync(KeySignRequest request, CancellationToken cancellationToken = new CancellationToken(), bool noWink = false) { if (request == null) { throw new ArgumentNullException(nameof(request)); } log.Info(">> authenticate"); var applicationSha256 = request.ApplicationSha256; var challengeSha256 = request.ChallengeSha256; var keyHandle = request.KeyHandle; log.Info(" -- Inputs --"); log.Info(" applicationSha256: " + applicationSha256.ToHexString()); log.Info(" challengeSha256: " + challengeSha256.ToHexString()); log.Info(" keyHandle: " + keyHandle.ToHexString()); var keyPair = dataStore.GetKeyPair(keyHandle); var counter = dataStore.IncrementCounter(); var userPresent = userPresenceVerifier.VerifyUserPresence(); if ((userPresent & UserPresenceVerifierConstants.UserPresentFlag) == 0) { return(TestOfUserPresenceRequired <KeySignResponse>()); } var signedData = RawMessageCodec.EncodeKeySignSignedBytes(applicationSha256, userPresent, counter, challengeSha256); log.Info("Signing bytes " + signedData.ToHexString()); var signature = crypto.Sign(signedData, keyPair.PrivateKey); log.Info(" -- Outputs --"); log.Info(" userPresence: " + userPresent); log.Info(" counter: " + counter); log.Info(" signature: " + signature.ToHexString()); log.Info("<< authenticate"); var response = new KeySignResponse(userPresent, counter, signature); var responseData = RawMessageCodec.EncodeKeySignResponse(response).Segment(); var apdu = new ApduResponse(ApduResponseStatus.NoError, responseData); var keyResponse = new KeyResponse <KeySignResponse>(apdu, response, KeyResponseStatus.Success); return(TaskEx.FromResult(keyResponse)); }
public ApduCollection TransmitAPDU(IZvtApdu apdu) { foreach (IApduHandler apduHandler in _apduHandlers) { apduHandler.StartCommand(); } _transport.Transmit(_transport.CreateTpdu(apdu)); ApduCollection responses = new ApduCollection(); while (true) { byte[] apduData = _transport.ReceiveResponsePacket(); byte[] apduCopy = new byte[apduData.Length]; Array.Copy(apduData, apduCopy, apduData.Length); IZvtApdu responseApdu = ApduResponse.Create(apduData); if (responseApdu == null) { throw new ArgumentException("Could not retrieve response"); } if (this.ResponseReceived != null) { ResponseReceived(responseApdu); } responses.Add(responseApdu); CallResponseApduHandlers(apdu, responseApdu); if (IsCompletionPacket == null && InternalIsCompletionPacket(apdu, responseApdu)) { break; } else if (IsCompletionPacket != null && IsCompletionPacket(apdu, responseApdu)) { break; } } return(responses); }
public ApduOperationResult UpdateLedAndBuzzer(Card card, byte ledState, byte t1, byte t2, byte repetitionNumber, byte buzzer) { var bytesToSend = new byte[9]; bytesToSend[0] = 0xFF; bytesToSend[1] = 0x00; bytesToSend[2] = 0x40; bytesToSend[3] = ledState; bytesToSend[4] = 0x04; bytesToSend[5] = t1; bytesToSend[6] = t2; bytesToSend[7] = repetitionNumber; bytesToSend[8] = buzzer; const int responseCodeLength = 2; ApduResponse response = SendAPDU(card, bytesToSend, responseCodeLength); return(ReturnCodeManager.IsApduSuccessful(response)); }
private GPResponse SendCommand(GPCommand apduCommand) { if (wrapper == null) { ApduResponse response = cardInterface.SendCommand(apduCommand); if (response is GPResponse) { return((GPResponse)response); } } else { GPCommand wrapped = Activator.CreateInstance(apduCommand.GetType()) as GPCommand; wrapped.ApduResponseType = apduCommand.ApduResponseType; wrapped.Deserialize(wrapper.Wrap(apduCommand)); ApduResponse response = cardInterface.SendCommand(wrapped); if (response is GPResponse) { return((GPResponse)response); } } throw new PersoException("Error returned from card"); }
FinalCombinationSelection_Step3_From_3_3_3_3(CardQProcessor cardInterfaceManager, TerminalSupportedKernelAidTransactionTypeCombination supportedKernelAidCombination, CardKernelAidCombination candidate, TLV iad, TLV scriptData) { string finalAdfName = Formatting.ByteArrayToHexString(candidate.AdfNameTag.Value); #region 3.3.3.3 if (candidate.ExtendedSelectionTag.IsPresent() && ((TerminalSupportedContactlessKernelAidTransactionTypeCombination)supportedKernelAidCombination).ExtendedSelectionSupportFlag != null && (bool)((TerminalSupportedContactlessKernelAidTransactionTypeCombination)supportedKernelAidCombination).ExtendedSelectionSupportFlag) { finalAdfName = finalAdfName + Formatting.ByteArrayToHexString(candidate.ExtendedSelectionTag.Get().Value); } #endregion #region 3.3.3.4 ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName)) as EMVSelectApplicationResponse; EMVSelectApplicationResponse response; if (cardResponse is EMVSelectApplicationResponse) { response = (EMVSelectApplicationResponse)cardResponse; } else { throw new EMVProtocolException("Pre-processing transmit error: try again"); } #endregion #region 3.3.3.5 if (!response.Succeeded) #endregion { if (iad != null || scriptData != null) { return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.EndProcess, UIRequestOnOutcomePresent = true, UserInterfaceRequest = new UserInterfaceRequest() { MessageIdentifier = MessageIdentifiersEnum.InsertSwipeOrTryAnotherCard, Status = StatusEnum.ReadyToRead }, UIRequestOnRestartPresent = false }, response, supportedKernelAidCombination)); } else { return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.CombinationSelection_StartC }, response, supportedKernelAidCombination)); } } TLV ttqInPDOL = response.GetPDOLTags().Get(EMVTagsEnum.TERMINAL_TRANSACTION_QUALIFIERS_TTQ_9F66_KRN.Tag); #region 3.3.3.6 if (finalAdfName.StartsWith(Enum.GetName(typeof(RIDEnum), RIDEnum.A000000003))) #endregion { if (((TerminalSupportedContactlessKernelAidTransactionTypeCombination)supportedKernelAidCombination).KernelEnum == KernelEnum.Kernel3) { if (response.GetPDOLTags().Count == 0 || ttqInPDOL == null) { if (TerminalSupportedKernelAidTransactionTypeCombinations.SupportedContactlessCombinations.Where(x => x.KernelEnum == KernelEnum.Kernel1).ToList().Count > 0) { //switch kernel to enable to kernel 1 TerminalSupportedKernelAidTransactionTypeCombination val = TerminalSupportedKernelAidTransactionTypeCombinations.SupportedContactlessCombinations.Where(x => x.KernelEnum == KernelEnum.Kernel1).ElementAt(0); return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.KernelActivation_StartD }, response, val)); } else { return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.CombinationSelection_StartC }, response, supportedKernelAidCombination)); } } } } //we will not support Application Selection Registered Proprietary Data (ASRPD) and continue as if the data was not present return(Tuple.Create( new EMVTerminalProcessingOutcome() { NextProcessState = EMVTerminalPreProcessingStateEnum.KernelActivation_StartD }, response, supportedKernelAidCombination)); }
public static KeyResponse <TData> Empty(ApduResponseStatus apduStatus, KeyResponseStatus status) { return(new KeyResponse <TData>(ApduResponse.Empty(apduStatus), null, status)); }
public KeyResponse(ApduResponse raw, [CanBeNull] TData data, KeyResponseStatus status) { Raw = raw; Status = status; Data = data; }
private ApduResponse SendAPDU(Card card, byte[] bytesToSend, int expectedRequestLength) { Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU started"); Logger.TraceEvent(TraceEventType.Verbose, 0, "bytesToSend: {0}", BitConverter.ToString(bytesToSend)); Logger.TraceEvent(TraceEventType.Verbose, 0, "card connection handle: {0}", card.ConnectionHandle); Logger.Flush(); IntPtr cardConnectionHandle = card.ConnectionHandle; // establish a new temporary connection in case of context mismatch if (card.ThreadId != Thread.CurrentThread.ManagedThreadId) { Logger.TraceEvent(TraceEventType.Verbose, 0, string.Format("Card context mismatch. Original thread: {0}. Current thread: {1}", card.ThreadId, Thread.CurrentThread.ManagedThreadId)); Logger.Flush(); if (!_cardConnectionManager.IsConnectionExist(card.InternalUid, Thread.CurrentThread.ManagedThreadId)) { // establish a new connection var connectionResult = Connect(card.CardreaderName, card.InternalUid); if (!connectionResult.IsSuccessful) { return(new ApduResponse { ReturnCode = connectionResult.StatusCode, RecvBuff = new byte[0], ResponseLength = 0 }); } // use a handle of a new connection cardConnectionHandle = connectionResult.ConnectedCard.ConnectionHandle; Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: new connection established. Handle: " + cardConnectionHandle); } else { cardConnectionHandle = _cardConnectionManager .GetConnection(card.InternalUid, Thread.CurrentThread.ManagedThreadId); Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU: existed card context found. Handle: " + cardConnectionHandle); } } var recvBuff = new byte[500]; WinscardWrapper.SCARD_IO_REQUEST pioSendRequest; pioSendRequest.dwProtocol = card.Protocol; pioSendRequest.cbPciLength = PciLength; int returnCode = WinscardWrapper.SCardTransmit( cardConnectionHandle, ref pioSendRequest, ref bytesToSend[0], bytesToSend.Length, ref pioSendRequest, ref recvBuff[0], ref expectedRequestLength); Logger.TraceEvent(TraceEventType.Verbose, 0, "SendAPDU ended. Return code: " + returnCode); Logger.Flush(); //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379804(v=vs.85).aspx //The pcbRecvLength should be at least n+2 and will be set to n+2 upon return. var result = new ApduResponse { RecvBuff = recvBuff, ResponseLength = expectedRequestLength, ReturnCode = returnCode }; return(result); }
public Task <KeyResponse <string> > GetVersionAsync(CancellationToken cancellationToken = new CancellationToken()) { var keyResponse = new KeyResponse <string>(ApduResponse.Empty(ApduResponseStatus.NoError), U2FConsts.U2Fv2, KeyResponseStatus.Success); return(TaskEx.FromResult(keyResponse)); }
CreateCandidateListByDirMethod(CardQProcessor cardInterfaceManager) { List <Tuple <TerminalSupportedKernelAidTransactionTypeCombination, CardKernelAidCombination> > candidateList = new List <Tuple <TerminalSupportedKernelAidTransactionTypeCombination, CardKernelAidCombination> >(); foreach (TerminalSupportedKernelAidTransactionTypeCombination kc in TerminalSupportedKernelAidTransactionTypeCombinations.SupportedContactCombinations) { string finalAdfName = Enum.GetName(typeof(AIDEnum), ((TerminalSupportedContactKernelAidTransactionTypeCombination)kc).AIDEnum); #region 12.3.3 Step 1 ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName)) as EMVSelectApplicationResponse; #endregion if (!(cardResponse is EMVSelectApplicationResponse)) { throw new EMVProtocolException("Pre-processing transmit error: try again"); } EMVSelectApplicationResponse response = (EMVSelectApplicationResponse)cardResponse; NextAID: #region 12.3.3 Step 2 if (response.SW1 == 0x6A && response.SW2 == 0x81) //card blocked { throw new Exception("Card blocked"); } if (response.SW1 == 0x6A && response.SW2 == 0x81) //command not supported { throw new Exception("Select command not supported"); } if (response.SW1 == 0x6A && response.SW2 == 0x82) //file not found { continue; } #endregion if (!response.Succeeded && !(response.SW1 == 0x62 && response.SW2 == 0x83)) { throw new Exception("Select command failed"); } if (response.GetDFName() == finalAdfName) { //full match if (response.Succeeded) //i.e. app not blocked 0x6283 { TLV adfNameTag = response.GetDFNameTag(); TLV applicationPriorityIndicatorTag = response.GetApplicationPriorityindicatorTag(); TLV preferedName = response.GetPreferredNameTag(); TLV appLabel = response.GetApplicationLabelTag(); Optional <TLV> extendedSelectionTag = Optional <TLV> .CreateEmpty(); candidateList.Add(Tuple.Create(kc, new CardKernelAidCombination() { AdfNameTag = adfNameTag, ApplicationPriorityIndicatorTag = applicationPriorityIndicatorTag, ApplicationPreferredName = preferedName, ApplicationLabel = appLabel, ExtendedSelectionTag = extendedSelectionTag, })); continue; } } if (response.GetDFName().StartsWith(finalAdfName)) { //partial match if (((TerminalSupportedContactKernelAidTransactionTypeCombination)kc).ApplicationSelectionIndicator) { if (response.Succeeded) //i.e. app not blocked 0x6283 { TLV adfNameTag = response.GetDFNameTag(); TLV applicationPriorityIndicatorTag = response.GetApplicationPriorityindicatorTag(); TLV preferedName = response.GetPreferredNameTag(); TLV appLabel = response.GetApplicationLabelTag(); Optional <TLV> extendedSelectionTag = Optional <TLV> .CreateEmpty(); candidateList.Add(Tuple.Create(kc, new CardKernelAidCombination() { AdfNameTag = adfNameTag, ApplicationPriorityIndicatorTag = applicationPriorityIndicatorTag, ExtendedSelectionTag = extendedSelectionTag, ApplicationPreferredName = preferedName, ApplicationLabel = appLabel, })); continue; } else { ApduResponse cardResponseNext = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName, true)) as EMVSelectApplicationResponse; if (!(cardResponse is EMVSelectApplicationResponse)) { throw new EMVProtocolException("Pre-processing transmit error: try again"); } response = (EMVSelectApplicationResponse)cardResponse; if (response.Succeeded || response.SW1 == 0x62 || response.SW1 == 0x63) { goto NextAID; } } } } } return(candidateList); }