/// <summary> /// Wraps the PCSC function /// LONG SCardTransmit( /// SCARDHANDLE hCard, /// LPCSCARD_I0_REQUEST pioSendPci, /// LPCBYTE pbSendBuffer, /// DWORD cbSendLength, /// LPSCARD_IO_REQUEST pioRecvPci, /// LPBYTE pbRecvBuffer, /// LPDWORD pcbRecvLength /// ); /// </summary> /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param> /// <returns>An APDUResponse object with the response from the card</returns> public override APDUResponse Transmit(APDUCommand ApduCmd) { // Must verify that it works with all type of cards uint outputLength = (ApduCmd.Le == 0) ? APDUResponse.MAX_LENGHT :(ApduCmd.Le + APDUResponse.SW_LENGTH); byte[] ApduBuffer = null; byte[] ApduResponse = new byte[outputLength]; PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request(); ioRequest.Protocol = protocol; ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest); // Build the command APDU if (ApduCmd.Data == null) { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well ApduBuffer[4] = (byte)ApduCmd.Le; } else { int apduBufferLengh = (ApduCmd.Class == 0x90) ? APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length + 1 : APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length; ApduBuffer = new byte[apduBufferLengh]; Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length); ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length; if (ApduCmd.Class == 0x90) { ApduBuffer[apduBufferLengh - 1] = 0; } } ApduBuffer[0] = ApduCmd.Class; ApduBuffer[1] = ApduCmd.Ins; ApduBuffer[2] = ApduCmd.P1; ApduBuffer[3] = ApduCmd.P2; lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength); ThrowSmartcardException("SCardTransmit", lastError); byte[] responseData = new byte[outputLength]; Buffer.BlockCopy(ApduResponse, 0, responseData, 0, (int)outputLength); string apduString = string.Format("APDU Buffer[{0}] => Response[{1}]", ByteArray.ToString(ApduBuffer), ByteArray.ToString(responseData)); apduTrace.Add(apduString); Trace.WriteLine(apduString); return(new APDUResponse(responseData)); }
/// <summary> /// Wraps the PCSC function /// LONG SCardTransmit( /// SCARDHANDLE hCard, /// LPCSCARD_I0_REQUEST pioSendPci, /// LPCBYTE pbSendBuffer, /// DWORD cbSendLength, /// LPSCARD_IO_REQUEST pioRecvPci, /// LPBYTE pbRecvBuffer, /// LPDWORD pcbRecvLength /// ); /// </summary> /// <param name="ApduCmd">APDUCommand object with the APDU to send to the card</param> /// <returns>An APDUResponse object with the response from the card</returns> public override APDUResponse Transmit(APDUCommand ApduCmd) { // Must verify that it works with all type of cards uint outputLength = (ApduCmd.Le == 0) ? APDUResponse.MAX_LENGHT : (ApduCmd.Le + APDUResponse.SW_LENGTH); byte[] ApduBuffer = null; byte[] ApduResponse = new byte[outputLength]; PCSC.SCard_IO_Request ioRequest = new PCSC.SCard_IO_Request(); ioRequest.Protocol = protocol; ioRequest.PciLength = (uint)Marshal.SizeOf(ioRequest); // Build the command APDU if (ApduCmd.Data == null) { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1]; // Pass the Le = 0 as well ApduBuffer[4] = (byte)ApduCmd.Le; } else { ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + ApduCmd.Data.Length]; Buffer.BlockCopy(ApduCmd.Data, 0, ApduBuffer, APDUCommand.APDU_MIN_LENGTH + 1, ApduCmd.Data.Length); ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = (byte)ApduCmd.Data.Length; } ApduBuffer[0] = ApduCmd.Class; ApduBuffer[1] = ApduCmd.Ins; ApduBuffer[2] = ApduCmd.P1; ApduBuffer[3] = ApduCmd.P2; lastError = PCSC.SCardTransmit(cardHandle, ref ioRequest, ApduBuffer, (uint)ApduBuffer.Length, IntPtr.Zero, ApduResponse, out outputLength); ThrowSmartcardException("SCardTransmit", lastError); byte[] ApduData = new byte[outputLength]; Buffer.BlockCopy(ApduResponse, 0, ApduData, 0, (int)outputLength); return(new APDUResponse(ApduData)); }