为了提高内部网络数据的安全性,分析了网络驱动程序接口规范( NDIS)以及Windows网卡驱动程序,我们提出了一种基于NDIS的网络数据链路层加密方案。

一、Windows环境下网卡驱动程序

1、网络驱动程序接口规范NDIS

Microsoft和3Com公司于1989年联合开发出了网络驱动程序接口规范NDIS(Network DriverInterface Specification)。NDIS规范了网络驱动程序间的标准接口,它使不同的传输可以采用一种通用的方式来访问由不同厂商制造的网卡。网络驱动程序不是直接调用操作系统的例程,而是通过NDIS进行系统调用,而NDIS驱动程序所存在的环境都是由NDIS库(Ndis.sys)所创建的,这个库输出一组标准接口,提供一个形如NdisXxx的系统函数集,使各NDIS驱动程序不需要直接与操作系统进行通信。

NDIS支持下列几种网络驱动程序形式:微端口驱动程序( Miniport drivers)、中间驱动程序(In-tennediate drivers)和协议驱动程序(Protocol drir-ers)。NDIS各层驱动程序以及它们之间的关系如图1所示:

数据链路层加密方法

2、网卡驱动程序

在windows环境下,网卡驱动程序对应于NDIS的微端口驱动程序…,微端口驱动程序工作在数据链路层,是与网络接口卡( NIC)结合最紧密的一层驱动程序.它调用NDIS库提供的接口函数来完成NIC与上层驱动程序之间的相互通讯.NDIS库导出一组函数集合(NdisXxx函数)来封装所有微端口需要调用的操作系统函数,而微端口也输出一组MiniportXxx函数供NDIS和上层驱动程序调用。

二、链路加密方案的设计与实现

1、设计思想

数据链路层是OSI系统结构中的第二层,如果采用链路加密,则网络中每条通信链路上的加密是独立实现的。对每条链路可以使用不同的密钥,这样,当某条链路受到破坏时也不会导致其他链路上传递的加密信息被解出。

NDIS微端口驱动位于网络链路层,是网络驱动中与网卡结合最紧密的驱动程序。因此可以对微端口驱动程序进行改造,在驱动程序中实现对数据帧的截取,并调用加解密模块对数据进行加解密,如图2所示,对驱动程序的改造大体可以分为两步:截取数据帧和加解密模块的实现。

数据链路层加密方法

(1)截取数据帧

NDIS库为微端口驱动程序提供了一系列接口函数,微端口驱动程序可以利用这些函数在主机与网络之间建立联系,也可以利用这些函数来截取数据。

在发送本机数据到网卡之前,可以在微端口驱动程序中加入截取子程序截获数据帧,并把数据帧送人加密模块进行加密,然后将加密后的密文送人网卡缓冲区中。接收数据时,从网卡缓冲区中接收的密文被送人主机内存,密文在送往上层网络驱动程序之前被接收截取子程序截获,并调用解密模块将其解密成明文,之后再将明文数据送交上层处理。

(2)加密解密模块

考虑到帧长的限制,对于数据帧加密要求必须保证其明文和密文长度相等,因此在加解密模块当中采用分组密码算法,分组密码的工作方式是将明文分成固定长度的组(块),用同一密钥对每一块加密,输出也是固定长度的密文,本文以DES为例。

考虑到软件加解密过程速度较慢,为了提高速度,直接将加解密模块嵌入到微端口驱动程序中,这样所有对数据的处理将全部在系统底层进行,大大提高了数据处理的效率,最后将所有模块集成在一起,编译生成网卡驱动程序MyDriver.SYS文件,分别安装在两台主机中进行测试。

2、方案实现

(1)实现工具及环境

本方案提出在微端口驱动程序中实施加解密,因此要选用适当的工具对微端口驱动程序进行改造。采用NuMega公司的驱动程序开发工具DriverStudio。其中DriverNetWorks是针对Windows网络驱动程序的开发工具。

(2)数据的发送和截取

数据的发送由上层协议驱动发起,发送的数据信息用一个NDIS_PACKET包来描述,NDIS库提供了一些函数来提取包中的信息,并对其进行处理。发送过程可分为两种情况:

1)当协议驱动程序有数据要发送时,启动传输操作,通过NIDS库调用微端口驱动程序的MyDriverSend函数。该函数调用的参数是一个指向NDIS_ PACKET包(描述将要发送的信息)的指针。驱动调用NdisQueryPacket函数得到包的长度和存放待发送包缓冲区的逻辑地址,然后设置MC上的寄存器将包发送出去,并返回—个发送成功的状态。

2)如果驱动程序不能立即发送包,则将它送到“待传输”队列中,然后由中断处理函数MyDriverHandlelnterrupt来完成发送。完成发送以后,调用NdisMSendComplete函数通知上层。

由于从上层传下来的数据包到微端口层被放在预先分配的缓冲区中。用NDIS提供的相应函数,可以得到该缓冲区的首地址和数据长度。因此,可在驱动程序中加入Send_lntercept子程序,利用NDIS提供的函数得到存放数据缓冲区的相应参数。然后调用加密模块接口函数DES_EN,子程序将加密后的密文发送到网络上。

3、数据的接收

数据接收是将网络上的数据帧接收到网卡缓冲区中,然后由驱动程序将缓冲区中的数据读人内存中。

网卡接收数据时会产生一个中断,因此驱动程序接收数据首先要在中断处理过程MyDnver-Handlelnterrup中进行,对于以太网卡,程序调用NdisMEthReceivelndicate函数将一个称为looka-head的数据传递给上层协议驱动,由协议驱动检查收到的数据是否符合协议要求。lookahead是指网卡中准备接收的数据的一部分,因为协议驱动判断微端口接收的数据是否符合协议要求时,不需要对所有数据都进行判断,只需对一部分数据(lookahead)进行判断即可。

如果协议驱动判断数据符合要求,就会调用微端口的MyDriverTmnsferData函数,将除looka-head之外剩余的数据传送到内存中,再交给上层驱动处理。当传送完毕时,调用NdisMEth-MReivelndicatecomplete函数通知上层驱动数据已经接收完毕。如果协议驱动检查数据不符合要求,就会终止接收过程。而已经传送到内存中的loo-kahead也会被下次接收到的数据覆盖掉。

4、加解密的实现

加解密实现的主要思想是将加解密算法集成到驱动程序中,本方案采用传统的DES加解密算法作为示例。

数据在被送入加密模块之前已经成帧,前14个字节存放的是源地址、目的地址和数据长度。发送截取函数Send_lntercept得到将要加密的数据长度和起始地址后,调用加密模块的接口函数DES_ENCRYPT,从数据的第15个字节开始进行加密,这样就将除地址和数据长度之外的所有数据都进行了加密。数据进行加密之后,驱动程序调用CardWrite函数将数据发送到网络中。

数据帧被接收到网卡缓冲区后,读人到内存当中的前14个字节数据为源地址、目的地址和数据长度。这14个字节的信息是以明文形式存在的。解密时,接收截取子程序Receive_lntercept调用解密模块接口函数DES—DECRYPT,从密文数据的第15个字节开始进行解密运算,解密之后将数据存人预先分配的缓冲区Prebuffer中,此后,驱动程序无论调用NdisMEtbRecei、relndicate函数,还是MyDriverTransferData函数,都是从缓冲区PrebuflFer中读取数据,而不是从网卡缓冲区中读取,直至解密过程结束。

小知识之链路层

数据链路层的最基本的功能是向该层用户提供透明的和可靠的数据传送基本服务。