繁体   English   中英

Xamarin/Android、智能卡、BulkTransfer

[英]Xamarin/Android, SmartCard, BulkTransfer

因此,我的任务是编写代码来处理智能卡。 环境是C#.Net,Xamarin。智能卡读卡器(接触式,非NFC)连接到霍尼韦尔手持设备上。 因此,由于存在稀疏的部分,并且出于各种原因我不能只使用某些第三方库,因此我承担了它的任务。

Using Android.Hardware.Usb, I can get to the following.

UsbManager - created to context of application.
Scan connected USB devices to the handheld
Properly detecting the specific device.
Getting the configuration object.
Then to the interface
and finally finding the 3 endpoints.. Isochronous, Inbound and Outbound.
Request permission to use the specific device.
and finally Open the device for a UsbConnection handle.

因此,既然沟通的大门是敞开的,我显然需要向外发送请求并从相应的出站和入站端点获得回复。

我可以构建 APDU 命令的 BulkTransfer,并得到一个可以接收 2 个字节的响应。 然后我尝试使用 APDU 响应在入站端口上执行另一个 BulkTransfer,但它总是以 -1 失败。

我看过其他讨论设置通信协议、波特率等的帖子,但不确定这是否是问题所在。 我对这种细粒度的串行/USB 通信完全陌生。 不确定与设备进行来回通信的后续步骤。

这是我为连接到设备所做的工作的简要总结。 至于具体的设备,是一台Honeywell CN80手持扫描仪设备,附带CAC阅读器(也是Honeywell)。 至于我想做什么,只是想调用验证卡存在(或不存在)。 我并没有尝试将数据实际发送到设备,只是一个查询设备并获得正确答复的命令。

public void attemptingSmartCommunications()
{
   _myUsbManager = (UsbManager)_myMainActivity.GetSystemService(Context.UsbService);
   foreach (var d in _myUsbManager.DeviceList)
   {  // method checks the device for proper VID/PID
      var dev = d.Value;
      if (isExpectedDevice(dev))
      {
         for (var dc = 0; dc < dev.ConfigurationCount; dc++)
         {
            // SHOULD only be 1 configuration from what I have encountered.
            _myUsbConfiguration = dev.GetConfiguration(dc);

            for (var di = 0; di < _myUsbConfiguration.InterfaceCount; di++)
            {
               _myUsbInterface = _myUsbConfiguration.GetInterface(di);
               // Add on context of each endpoint
               for (var ep = 0; ep < _myUsbInterface.EndpointCount; ep++)
               {
                  var intEndpoint = _myUsbInterface.GetEndpoint(ep);

                  // which one do we need, store into their own respecive properties
                  // for in/out/isochronous
                  switch (intEndpoint.Address.ToString())
                  {
                     case "XferIsochronous":
                        // Control pipe for communication
                        _myIsochronousEndpoint = intEndpoint;
                        break;

                     case "130":
                        // Read IN FROM the USB Device with response
                        _myInEndpoint = intEndpoint;
                        break;

                     case "131":
                        // Write OUT TO the USB Device with command/request
                        _myOutEndpoint = intEndpoint;
                        break;

                  }
               }

               // now, I have the endpoints to request send and read back, make sure permission
               if( _myUsbManager.HasPermission(_myUsbDevice))
               {
                  myConnection = _myUsbManager.OpenDevice(_myUsbDevice);
                  var apdu = MyStaticSmartCardAPDUCommand;
                  // prepares the 4-byte request of CLA, INS, P1, P2 (no data in request)
                  var byteBuffer = apdu.CommandAsBytes(); 
                  var bufferLen = byteBuffer.Length;
                  var resultBytes = _myUsbDeviceConnection.BulkTransfer(_myOutEndpoint, byteBuffer, bufferLen, 2000);
                  // I get indication of 2 byte response
                  if( resultBytes > 0 )
                  {
                     // default buffer prepared with 4 bytes.  SW1, SW2 + 2 expected bytes
                     var apduResp = new APDUResponse(resultBytes);
                     byteBuffer = apduResp.GetResponseBuffer();
                     var responseStatus = _myUsbDeviceConnection.BulkTransfer(_myInEndpoint, byteBuffer, byteBuffer.Length, 3000);

                     // HERE is where it always fails.  
                     // Am I on the right track?  Completely out of it?
                  }
               }
            }
         }
      }
   }
}

(本来想写评论的,但是写的太长了……)

从技术上讲,有两种可能性,无需使用制造商的驱动程序:

  1. 读写器采用标准的USB CCID协议 然后您需要在您的软件中实现该协议。 该协议在此处描述。 有一个开源实现libccid ,您可以将其用作参考。

  2. 阅读器使用一些专有协议 然后你需要从供应商那里得到协议描述并实现它。

要区分两者,请参阅阅读器规格和/或检查它的 USB 描述符。 您可能还想看看这里这里


一些额外的(随机)注释:

  • 使用专有协议的读者通常会模拟一个 USB 串口。 如果是这种情况,那么通过原始 USB 与读者通信是没有意义的——改用这个串行端口。

  • 我想阅读器供应商为此阅读器提供了一些 Android 驱动程序。 我不知道您不使用它们的原因,但您应该这样做。 Java 代码应该可以使用绑定库从 Xamarin 调用。 对于本机库,请使用P/Invoke (和 Xamarin 特定文档)。

  • 如果某些系统级智能卡 API 可用(例如 winscard),则使用它(如果可能,使用例如pcsc-sharp )。

  • 您在代码中所做的是将原始命令 APDU 发送到 USB 端点,并期望响应 APDU 作为响应。 您肯定需要将命令 APDU 包装为特定于协议的格式(具体格式取决于读者)。


免责声明:我不是 Xamarin 专家所以请验证我的想法。

祝你的项目好运!


编辑> 您可能还会发现这些帖子很有趣: 1 , 2


EDIT2> 有一个PoC javascript CCID 实现,您可能会发现它更容易理解。

看看官方驱动程序如何使用具有CCID 解析器Wireshark与读者通信也很有启发性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM