U盘唯一性标识信息的构建与识别方法
2009-06-26
作者:李俊艳1,2, 高 杨2,3,
摘 要:根据涉密存储介质保密管理的要求,以U盘为例,提出一种新颖的、以USB协议和大容量存储类协议为基础的移动存储介质管理架构。存储介质的唯一性标识由VID、PID和硬件序列号组成。同时还提出了基于CY7C67300嵌入式主机控制器的USB总线介质管理方案。通过USB总线枚举方式,逐一识别介质唯一性标识并通过超级终端显示。测试结果证明,该标识和识别方法可以用于移动存储介质安全管理系统,从而使涉密移动存储介质处于实时监控状态下,大大减少了泄密风险。
关键词:信息安全; 移动存储介质; 唯一性标识; 嵌入式USB主机控制器; USB总线枚举
按照保密管理规定,涉密单位职工使用完U盘等移动存储介质必须当天按时归还保密员,并存储在密码文件柜中(如部队的枪支入架)。保密文件柜由保密员人工管理,涉及借出、归还、监督、提醒等事项,难免疏漏。若个别人员违规(未经审批许可)携带涉密U盘外出,可能导致涉密U盘丢失或涉密数据失窃,泄漏国家或商业秘密,造成巨大的损失。因此,涉密U盘的保密管理,需要依靠创新的技术手段,保障保密管理规章制度的贯彻落实。为了实现涉密U盘保密管理的智能化“机控”,需要为每个U盘定义一个可查询、不易修改的唯一性标识(Unique identifier),且该标识应很容易与使用者绑定,从而使涉密U盘的保密管理责任到人,以减少泄密隐患。
本文以通用串行总线USB1.0、USB2.0协议为基础,采用CY7C67300单芯片实现嵌入式USB主机控制器,完成该控制器对U盘的控制以及读取U盘唯一性标识信息的功能。
1 工作原理
1.1 唯一性标识的构建
USB控制/批量/中断CBI(Control/Bulk/Interrupt)传输协议和USB Bulk-Only协议中规定,U盘等符合大容量存储类MSC(Mass Storage Class)协议的设备,如果其序列号索引值不为0,则U盘内必定含有一个唯一的序列号与之匹配[1-2]。如表1所示,在其设备描述符中偏移值为16的字段只规定了其序列号的索引值,如果其索引值为0,则说明此设备不含序列号,反之,设备必定含有一个唯一的序列号。序列号的格式如表2所示,表中,第一项为序列号的长度,其最小值为26;第二项为序列号的类型,其值为3,说明序列号为字符串描述符;第三至第n×2项为序列号的内容。USB CBI 和Bulk-Only协议中规定序列号至少由12个有效的数字字符组成,这些数字字符的有效范围为:数字0~9,字符A~F。
本文采用16 bit VID(设备描述符偏移量为8)+16 bit PID(设备描述符偏移量为10)+序列号构成GUID(全球唯一ID)作为U盘的唯一性标识。
1.2 唯一性标识的识别
如前所述,获取U盘唯一性标识就是获取设备描述符中的VID、PID和字符串描述符中的序列号。本文采用USB总线枚举方式获得U盘的唯一性标识。
总线枚举是指对总线上接入的USB设备进行识别和寻址操作。当USB主机发现有设备连接时,立刻通过默认的地址0发送读取设备描述符的命令,然后利用控制传输的标准命令为其动态配置设备地址,再通过该地址继续读取有关设备、配置、接口以及字符串描述符,并建立有关信息的资料区[3]。这些信息主要包括VID、PID和端点信息等。其中,VID、PID的获取是通过Get_descriptor( )标准请求命令实现的。字符串描述符信息的获取没有明确的定义,需要开发一种用于获取字符串信息的命令请求。
本文利用嵌入式控制器完成USB主机功能,通过USB主机实现总线枚举、控制传输以及获取设备描述符的标准请求命令和获取字符串描述符的请求命令,从而实现U盘唯一性标识信息识别装置的设计。
2 装置设计
2.1 硬件结构
U盘唯一性标识识别装置的硬件结构框图如图1所示。采用CY7C67300作为核心处理器,CY16工作在独立模式下,控制CY7C67300芯片内部的USB串行接口引擎SIE(Serial Interface Engine)完成USB主机的功能,控制LTC3186芯片进行电平转换,完成异步串行收发器UART可以用来调试。通过I2C接口控制EEPROM以下载程序。通过外部存储器接口控制外部存储器以扩展代码和数据存储空间。
核心处理芯片CY7C67300是CYPRESS公司的嵌入式主机/外设控制器,其内部结构如图2所示。主机部分包括高性能16位48 MHz RISC微处理器CY16,该处理器可以独立工作(独立模式),也可以与其他处理器协同工作(协处理器模式);2个SIE,每个可单独配置,有2个端口USB-A、USB-B;可配置的I/O电路模块能连接众多标准接口,高达16位可编双向数据I/O,多达32位通用I/O;4 K×16 bit内部掩模板ROM,内有基本输入输出系统BIOS,支持I2C、EEPROM,外部ROM、UART、USB等外设端口通信就绪状态;8 K×16 bit内部RAM能由用户配置;具有外接SRAM,DRAM和ROM存储器接口,芯片外部可以扩展512 KB存储空间;芯片内部集成有定时器和看门狗电路;工作电压3.3 V,100引脚TQFP封装。
2.2 嵌入式USB主机设计
采用CY7C67300芯片实现嵌入式USB主机,嵌入式主机结构如图3所示。
嵌入式主机由BIOS、框架结构(Frameworks)和应用驱动层(AppDrive)三部分组成。其工作原理为:Frameworks发现有新的设备连接时,创建一个device object(设备列表)并查询是否与USB大容量存储类驱动USB MSC Driver匹配,如果匹配,Frameworks则调用设备驱动程序中的start-device()函数;如果不匹配,则返回继续监测是否有新的设备连接。在嵌入式主机结构中,应用程序和设备驱动程序并未完全分开,而是集成在一起称之为AppDrive,当AppDrive开始运行时,它会创建USB请求块URBs(USB Requst Block)给Frameworks去处理。当URB处理完成后,Frameworks调用由AppDrive指定的回调函数。Frameworks利用在通用主机控制器接口UHCI(Universal Host Controller Interface)标准中定义的调度算法建立传输描述列表TD-List(Transfer Descriptor List)并将TD-List传输给EZ-HOST的BIOS去处理,BIOS返回一个新的TD-List状态信息给Frameworks,并将TD-List内容传给USB总线。Frameworks开始创建下一帧的TD-List,TD_List结构体定义[4]如下:
typedef struct TD
{ void *address;
uint16 length;
uint16 port_num;
uint16 ep;
uint16 pid;
uint16 dev_address ;
uint8 control;
uint8 status;
uint16 retry_cnt;
uint16 retry_xfer_type;
uint16 retry_active;
uint16 unused_3;
uint16 residue;
struct TD *next_TD;
} TD;
该结构体包含数据缓存的基地址、数据长度和端口号以及传输的包标识pid(packet identifier)、主机给设备分配的地址、控制位和状态位、重传次数、传输类型以及传输是否有效等成员变量。
2.2.1 嵌入式USB主机 BIOS
USB主机BIOS包含HUSB-SIE1-INIT-INT, HUSB-SIE2-INIT-INT和HUSB-RESET-INT3个软件中断,其中,HUSB-SIEx-INIT-INT(x=1,2)用于执行TD-List,主要实现以下功能:设置SIE为主机并执行初始化,检测是否有等待传输的TD-List,如果有,继续进行TD-List的传输;通过USB传输所有的TD 数据;更新TD状态并对错误进行处理。HUSB-RESET-INT执行以下3个功能:USB 复位;速度检测;帧开始SOF(Start of Frame)和包结束EOP(End of Packet)产生。
2.2.2 USB主机控制器 Frameworks
自主开发USB主机固件任务相当艰巨,而CYPRESS公司提供了大量的USB主机固件程序,系统在此基础上可进行修改,节约了大量的开发时间,提高了系统完成的效率。
当系统上电时,Frameworks会不断地查询是否有新的设备连接,如果发现有新的设备,Frameworks会建立如下所示的设备对象。
typedef struct USB_DEVICE
{ uint8 sie;
uint8 port;
uint8 address;
uint8 hub_port;
uint8 speed;
uint8 EP0_max_pkt;
uint8 enum_state;
uint8 otg_attributes;
USB_DEVICE_DESCRIPTOR dev_descr;
STRING_DESCRIPTOR_NODE dev_string_descr;
uint8 cfg_descr[];
uint8 setup_packet_buffer[]
USB_INTERFACE_DESCRIPTOR *inf_descr;
USB_HUB_DESCRIPTOR hub_descr;
void *hub_context;
void *msc_context;
bool idleCheck;
} USB_DEVICE;
如果该设备对象与设备驱动程序匹配,则开始填充该设备对象的信息,包括设备所在的端口、地址或集线器接口、速度、设备描述符、字符串描述符等[4]。Frameworks利用URB获取新设备的信息,通过URB建立1个或多个TD,通过BIOS与USB总线交换信息。
2.2.3 MSC驱动
Frameworks发现有设备连接时,根据应用驱动程序发出的URB获得设备信息。U盘属于MSC(Mass Storage Class)设备,所以必须开发MSC驱动。驱动实现结构图如图4所示,分三层任务:初始化任务Init_Task,闲置任务Idle_Task,回调任务CallBack_Tasks。其中,Init_Task负责设置Idle_Task和任何一个CallBack_Tasks、Init_Task只运行一次,执行完Init_Task后必须释放其占用的内存,把控制权交还给调用者。
每个Idle_Task建立一个Idle_Chain与上一层即应用层(Applycation)的Idle_Task相连接,负责寻找要做的工作。
CallBack_Tasks负责执行Idle_Task寻找的工作,执行后导致某些事件发生,这些事件包括硬件中断、软件中断或在Idle_Task中建立的处理过程。
MSC驱动是通过实现CLASS-DRIVE结构体定义的成员变量函数:mscdrvr_init( )、mscdrvr_start( )、mscdrvr_stop( )、mscdrvr_run( )、mscdrvr_ioctl( )实现的。其中CLASS_DRIVER类型mscdrvr_driver结构体成员赋值如下:
CLASS_DRIVER mscdrvr_driver =
{
0x08, /* uint8 class; */
0x00, /* uint8 subclass; */
0x50, /* uint8 protocol; */
0x0000, /* uint16 vendor_ID; */
0x0000, /* uint16 product_ID; */
mscdrvr_init, /* void (*init)( void ); */ mscdrvr_start,
/*uint16 (*start)( USB_DEVICE *dev ); */
mscdrvr_stop, /* uint16 (*stop)(void); */
mscdrvr_run, /* void (*run)(void);
mscdrvr_ioctl, /* uint16 (*ioctl)( USB_DEVICE *, uint16,uint16, uint16 ); */
};
2.3 USB主机对设备的总线枚举以及请求命令实现
在以CY7C67300芯片为核心实现的USB主机控制器中,USB总线枚举过程如下:Frameworks通过一系列的URBs枚举设备:包括GetDescriptor()、UsbSetConfig()、UsbSetInterface()等USB标准请求命令,建立TD_List,实现控制传输,利用控制传输把请求命令传给BIOS,通过BIOS与USB总线进行通信,取得设备一系列信息。
2.3.1 控制传输的实现
控制传输较为复杂,分为 3 个步骤:初始设置、可选数据和状态信息步骤[5]。在初始设置中需要发送 8 字节的请求命令,创建请求命令的结构体如下:
typedef struct USB_DEVICE_REQUEST
{
uint8 bmRequestType;
uint8 bRequest
uint16 wValue
uint16 wIndex
uint16 wLength
} USB_DEVICE_REQUEST;
请求命令的各个字段分别为请求类型、请求命令、数值和索引以及获取的数据长度。
(1) 初始设置的实现
初始设置的任务就是要发送建立的 8 字节请求命令,控制传输的设置信息通过端点0进行传输。因此,设置USB_DEVICE_REQUEST指向USB_DEVICE结构体中的setup_packet_buffer[0],设置TD结构体的PID为PID_SETUP,端点号为端点0,TD地址为&setup_packet_buffer[0],发送内容即为setup_packet_buffer[0]中的请求命令。
(2) 可选数据的实现
请求命令的 wLength 字段指明了需要交换的数据长度,当值为0时表示没有可选数据;当值不为0时,设置TD结构体中的pid为PID_IN(数据传输方向为设备到主机)及PID_OUT(主机到设备)。length为传输数据的长度,address为&setup_packet_buffer[0],发送的内容即为setup_packet_buffer[0]中的数据。
(3) 状态信息的实现
在这个步骤中,主机发送控制传输的状态信息,实现过程如下:设置TD结构体中的PID为PID_OUT,端点地址为0,发送setup_packet_buffer[0]中的状态信息。
2.3.2请求命令实现
表3为获取设备描述符和字符串描述符的设备请求命令封装,其中设备描述符、语言ID和字符串描述符请求命令的bmRequestType字段为1 000 000,其D7=1说明数据传输的方向是设备至主机,D6..5=00表示为标准请求,D4..0=00 000表示为请求命令的接收端为设备。bRequest字段的内容都为Get_Descriptor,因为设备描述符中含有语言ID和字符串描述符的索引,所以字符串描述符和语言ID的获取都是通过获取设备描述符实现的。Get_Descriptor命令的wValue字段为0100,01代表描述符类型为设备描述符,00为描述符索引。wIndex字段为0,wLength为设备描述符结构体的长度。Get_LanguageID命令的wValue为0300,03代表描述符类型为字符串描述符,00为描述符索引;wIndex为0,wLength为字符串描述符长度。这个命令是获取U盘的语言ID,使语言ID作为获取字符串描述符命令的wIndex字段值,Get_Str_Descriptor命令的wValue为0303,descriptor_type为03代表该描述符为字符串描述符,descriptor_index为03说明获取U盘序列号的索引值为03,获取的字符串描述符的长度wLength为字符串描述符长度。
系统根据请求命令封装,分别实现Get_Descriptor()、Get_LanguageID()、Get_Str_Descriptor()函数,利用这些函数的返回值得到U盘的唯一性标识信息。
3 调试结果
采用CYPRESS公司提供的软件工具GNUPro作为调试工具。UART串口与PC主机的超级终端连接,当U盘插入系统时,超级终端上会自动输出该U盘的VID、PID和iSerialNumber。
获取U盘的唯一性标识的4个示例结果如下:
vid=0x066f
pid=0x8000
Serialn==3
LanguageID=0x0409
descriptorlength=0x0022
iserialnumber=0002F68C2AC54D98
vid=0x0204
pid=0x6025
serialn==3
LanguageID | =0x0409
descriptorlength=0x0022
iserialnumber=05185200BA923502
vid=0x0951
pid=0x160b
serialn==3
LanguageID = 0x0409
descriptorlength=0x0032
iserialnumber=0014780F99515C8718080051
vid=0x090c
pid=0x1000
serialn==3
LanguageID = 0x0409
descriptorlength=0x0022
iserialnumber=AA04012700007705
本文提出了一种U盘唯一性标识的构建和识别方法;设计了以CY7C67300为核心芯片的USB主机控制器,利用该主机控制器可完成USB总线枚举、控制传输和请求命令,根据请求命令对U盘唯一性标识进行识别。利用U盘的唯一性标识,可以实现涉密存储介质的网络化管理,远程监控中心可实时监控U盘的状态(借出、归还),结合相关的保密管理规定,就可以及时发现涉密U盘管理、使用的违规行为后及时报警。这种新颖的U盘唯一性标识信息的构建与识别方法,为涉密U盘的网络化、智能化保密管理奠定了基础。
参考文献
[1] Universal serial bus mass storage class control/bulk/interrupt (CBI) transport revision 1.1[S]. 2003-06-23.
[2] Universal serial bus mass storage class bulk-only transport specification revision1.0[S].http://www.usb.org/developers/docs, 1999-09-31.
[3] 刘思久,李文文,段天明.嵌入式通用USB-Host控制器[J].电测与仪表,2006,43(7):63-66.
[4] HYDE J. USB multi-role device design by example[M].CYPRESS, 2003.
[5] 谭刚. 基于MCF5249的USB主机的设计与实现[D].成都:电子科技大学,2005.