如何在 UEFI 应用程序中获取 USB Token飞天汽车 ePass 2003 FIPS USB Token序列号?

如何解决如何在 UEFI 应用程序中获取 USB Token飞天汽车 ePass 2003 FIPS USB Token序列号?

开发基于 UEFI 的应用程序以启用预启动身份验证使用 飞天汽车 ePass 2003 FIPS USB 令牌。我仍处于开发过程的初始阶段。

现在我可以使用 UsbIo->UsbGetDeviceDescriptor 协议获取令牌的制造商、产品代码。但是当我尝试查找序列号时,它抛出了一个错误

有没有其他方法可以找到USB Token的序列号?请帮我解决这个问题..

这是我查找序列号的示例代码

EFI_USB_DEVICE_DESCRIPTOR DevDesc;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
EFI_USB_CONfig_DESCRIPTOR     ConfigDescriptor;
EFI_USB_IO_PROTOCOL *UsbIo;

EFI_STATUS Status;
EFI_HANDLE *HandleBuffer = NULL;

BOOLEAN    LangFound;
UINTN      HandleCount;
UINT8      EndpointNumber;

CHAR16* ManufacturerString = NULL;
CHAR16* ProductString = NULL;
CHAR16* SerialNumber = NULL;
UINT16* LangIDTable;
UINT16 TableSize;
INTN Index;

int index;


unsigned char* device_descriptor,* ccid_descriptor;

EFI_USB_DEVICE_REQUEST  DevReq;
UINT32 Status_uint;
 
Status = gBS->LocateHandleBuffer( ByProtocol,&gEfiUsbIoProtocolGuid,NULL,&HandleCount,&HandleBuffer );
if (EFI_ERROR(Status)) {
    Print(L"ERROR: LocateHandleBuffer.\n");
    goto ErrorExit;
}

UINT8 usbIndex;

for (usbIndex = 0; usbIndex < HandleCount; usbIndex++) {
    Status = gBS->HandleProtocol( HandleBuffer[usbIndex],(VOID**)&UsbIo );
    if (EFI_ERROR(Status)) {
        Print(L"ERROR: Open UsbIo.\n");
        goto ErrorExit;
    }
 
    Status = UsbIo->UsbGetDeviceDescriptor( UsbIo,&DevDesc );
    if (EFI_ERROR(Status)) {
        Print(L"ERROR: UsbGetDeviceDescriptor.\n");
        goto ErrorExit;
    }


    Status = UsbIo->UsbGetConfigDescriptor( UsbIo,&ConfigDescriptor );
    if (EFI_ERROR (Status))
    {
        Print(L"UsbGetConfigDescriptor %d",Status);
        goto ErrorExit;
    }

        
    Status = UsbIo->UsbGetInterfaceDescriptor( UsbIo,&InterfaceDescriptor );
    if (EFI_ERROR (Status)) {
        Print(L"ERROR: UsbGetInterfaceDescriptor.\n");
        goto ErrorExit;
    }

    if (InterfaceDescriptor.InterfaceClass != CLASS_CCID) {
        continue;            
    }

    Print(L":::::::::::::::::::::: CCID ::::::::::::::::::::::\n");

    //
    // Get all supported languages.
    //
    TableSize = 0;
    LangIDTable = NULL;
    Status = UsbIo->UsbGetSupportedLanguages(UsbIo,&LangIDTable,&TableSize);
    if (EFI_ERROR(Status)) {
        Print(L"ERROR: UsbGetSupportedLanguages.\n");
        return Status;
    }

    /* Get Manufacturer string */
    for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
        ManufacturerString = NULL;
        Status = UsbIo->UsbGetStringDescriptor(UsbIo,LangIDTable[Index],DevDesc.StrManufacturer,&ManufacturerString);

        if (EFI_ERROR(Status) || (ManufacturerString == NULL)) {
            continue;
        }
        Print(L"StrManufacturer ::%s\n",ManufacturerString);
        FreePool(ManufacturerString);
        break;
    }

    /* Get Product string */
    for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
        ProductString = NULL;
        Status = UsbIo->UsbGetStringDescriptor(UsbIo,DevDesc.StrProduct,&ProductString);

        if (EFI_ERROR(Status) || (ProductString == NULL)) {
            continue;
        }
        Print(L"StrProduct ::%s\n",ProductString);
        FreePool(ProductString);
        break;
    }

    /* Get Serial string */
    for (Index = 0; Index < TableSize / sizeof(LangIDTable[0]); Index++) {
        SerialNumber = NULL;
        Status = UsbIo->UsbGetStringDescriptor(UsbIo,DevDesc.StrSerialNumber,&SerialNumber);

        if (EFI_ERROR(Status) || (SerialNumber == NULL)) {
            Print(L"Error in finding SerialNumber \n");
            continue;
        }

        Print(L"SerialNumber :: %s\n",SerialNumber);

        FreePool(SerialNumber);
        break;
    }

    Print(L"usbIndex ::%d\n",usbIndex);
    Print(L"Idvendor ::%d\n",DevDesc.Idvendor);
    Print(L"IdProduct ::%d\n",DevDesc.IdProduct);    
}

Print(L"\n");
FreePool(HandleBuffer);
return Status;

解决方法

据我所知,飞天科技 ePass2003 使用英飞凌 M7893 或 SLE 78CUFX5000PH (M7893-B) 安全芯片。

如您所见,ePass2003 的序列号并未存储在 USB 设备描述符中,而是存储在安全芯片中。

为了获取芯片全局数据,例如 OEM 信息、算法支持、FIPS 模式指示器、RAM 大小和序列号,使用了 GetData 原语。请参阅 M7893 编程指南。如果您可以访问它。

OpenSC 中 ePass2003 的驱动程序称为“epass2003”。源代码目前可在 https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-epass2003.c 获得。它依赖于 OpenSSL 和 ASN.1 以及一些非 EDK2 标头,但这些很容易解决。

如果您只需要序列号,那么通过研究 OpenSC ePass2003 驱动程序的工作原理,编写 UEFI 应用程序(或驱动程序)来获取该信息应该相当容易(提示 - 查看 {{1 }} 或者学习ePass2003 SDK,它可以从飞坦和其他地方免费获得。

2015 年 4 月发布的 UEFI 2.5 规范详细介绍了与智能卡相关的 2 个协议,即智能卡读卡器和智能卡边缘。

epass2003_get_serialnr

EDK2 目前不包含示例实现。但是,您可能对 Ludovic Rousseau 提供的 GPL2 许可示例实现感兴趣,该实现可在 typedef struct _EFI_SMART_CARD_READER_PROTOCOL { EFI_SMART_CARD_READER_CONNECT SCardConnect; EFI_SMART_CARD_READER_DISCONNECT SCardDisconnect; EFI_SMART_CARD_READER_STATUS SCardStatus; EFI_SMART_CARD_READER_TRANSMIT SCardTransmit; EFI_SMART_CARD_READER_CONTROL SCardControl; EFI_SMART_CARD_READER_GET_ATTRIB SCardGetAttrib; } EFI_SMART_CARD_READER_PROTOCOL; typedef struct _EFI_SMART_CARD_EDGE_PROTOCOL { EFI_SMART_CARD_EDGE_GET_CONTEXT GetContext; EFI_SMART_CARD_EDGE_CONNECT Connect; EFI_SMART_CARD_EDGE_DISCONNECT Disconnect; EFI_SMART_CARD_EDGE_GET_CSN GetCsn; EFI_SMART_CARD_EDGE_GET_READER_NAME GetReaderName; EFI_SMART_CARD_EDGE_VERIFY_PIN VerifyPin; EFI_SMART_CARD_EDGE_GET_PIN_REMAINING GetPinRemaining; EFI_SMART_CARD_EDGE_GET_DATA GetData; EFI_SMART_CARD_EDGE_GET_CREDENTIAL GetCredential; EFI_SMART_CARD_EDGE_SIGN_DATA SignData; EFI_SMART_CARD_EDGE_DECRYPT_DATA DecryptData; EFI_SMART_CARD_EDGE_BUILD_DH_AGREEMENT BuildDHAgreement; } EFI_SMART_CARD_EDGE_PROTOCOL; 获得。大约有 5 年历史且我尚未测试过的实现代码位于 https://github.com/LudovicRousseau/edk2/tree/SmartCard。也请阅读他的博客 (https://ludovicrousseau.blogspot.com/),因为他还提供了有用的示例应用程序。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?