1引言
在过去几年里Internet和嵌入式技术发展迅速,Internet在服务器、桌面机和包括PDA和小型电话的便携式电脑上应用迅速增长。随着更简单、资源更受限制连接到WEB的设备(探测器、家居设备、个人医疗设备)数量增长,这种趋势将会继续。具有传感和通信功能的嵌入式设备将计算机技术应用于今天不寻常的设备(现场监控,医疗紧急响应、战场管理和家居自动化)中变成可能。这些嵌入式应用都具有安全需要,没有足够的安全,攻击者可以控制这些嵌入式设备并引发灾难性的反应。
SSL[1]是今天在Internet上最流行的安全协议,它内建于很多流行的应用程序里,包括所有著名的WEB浏览器,并且广泛被信任用于加强敏感信息传输包括:在线银行,证券交易和电子商务。SSL 采用数字证书、对称/ 非对称密钥加密、消息摘要和数字签名等技术提供身份认证、数据保密、数据完整性三大安全服务,可以为嵌入式系统提供一个完善的安全解决方案。但现有大多数SSL协议实现都没有针对嵌入式系统,不适合于嵌入式Internet要求。
MatrixSSL[3]是针对小型应用程序和设备设计的嵌入式、开放源码SSLv3协议栈(商业版支持TLS协议)。它减少了将SSL整合进嵌入式工程的复杂性,使用一个简单的API和安全层,用户可以很容易地将MatrixSSL整合到它们的应用程序。Matrixssl使用工业界标准的加密算法(RC4、DES3、AES、RSA)和协议,它确保用户获得一个编译不到50K(Openssl[2]需要1M左右)的提供强大和可靠安全解决方案的库函数,并具有可插拔密码套件、算法和可移植性强等特点,可以方便定制密码套件和算法以及平滑地向多平台移植,非常适合在资源受限的嵌入式环境中使用。
2 MatrixSSL程序流程
MatrixSSL库函数没有针对某一具体的传输协议,它采用公共API方式可以非常理想的保护传输于任何虚拟通信通道上的数据,不但可用在TCP/IP上也可用于串口通信上,但主要的MatrixSSL整合用于保护在TCP套接字上计算机系统间的数据。由于MatrixSSL库函数没有专门针对TCP/IP,在使用时需要对公共API进行封装以满足在具体传输层上的需要。MatrixSSL提供了对公共API封装的一个套接字实例(可根据需要自行对公共API进行封装),通过调用封装的套接字API接口可以非常容易地实现SSL协议。下面将按照封装API套接字在应用程序中整合点来分析它们:
1)初始化MatrixSSL库函数
在使用Matrixssl前需要对协议进行初始化,调用公共API实现对库函数初始化:
int matrixSslOpen();//初始化库函数数据结构
int matrixSslReadKeys(sslKeys_t **keys, char *certFile, char *privFile,
char *privPass, char *trustedCAcertFiles);// 加载相关的证书和私钥文件
2)创建SSL会话连接
在初始完毕后,就可以创建会话和握手过程,Matrixssl将这两个功能在客户端和服务器端的一个封装函数中完成。客户端使用sslConnect替代原始的Connect完成SSL握手过程,并制定对服务器端证书的验证方式:
int sslConnect(sslConn_t **cp, SOCKET fd, sslKeys_t *keys, sslSessionId_t *id,
short cipherSuite, int (*certValidator)(sslCertInfo_t *t, void *arg));
服务器端用sslAccept函数代替传统的Accept函数完成握手过程,并制定对客户端证书的验证方式:
int sslAccept(sslConn_t **cp, SOCKET fd, sslKeys_t *keys,int (*certValidator)(sslCertInfo_t *t, void *arg), int flags);
3)进行数据传输
在握手完成后,就可以进行安全的数据传输了。在数据传输阶段,需要使用sslRead和sslWrite函数代替传统的read()和write()函数,完成对套接字的读写操作:
int sslRead(sslConn_t *cp, char *buf, int len, int *status);
int sslWrite(sslConn_t *cp, char *buf, int len, int *status);
4)结束SSL通信
当客户机和服务器之间完成数据通信后,调用下面函数来释放SSL资源:
void sslWriteClosureAlert(sslConn_t *cp);//发出关闭连接的警告
void sslFreeConnection(sslConn_t **cpp)//关闭由握手过程中打开的会话并释放缓冲区
void matrixSslFreeKeys(sslKeys_t *keys); // 释放创建的密钥
void matrixSslClose();//清除Matrixssl库函数
MatrixSSL对普通网络编程接口也进行了封装,方便了编程调用,以下是封装的普通网络编程接口(也可直接调用网络编程接口而不封装):
SOCKET socketListen(short port,int *err) // 创建一个新的套接字并绑定到给定端口
SOCKET socketAccept(SOCKET listenfd, int *err);// 为到来的请求创建一个套接字
SOCKET socketConnect(char *ip, short port, int *err);// 创建一个新的套接字并且连接到给定IP和端口的监听套接字
Void socketShutdown(SOCKET sock);// 关闭一个套接字
void setSocketBlock(SOCKET sock);// 设置一个套接字为阻塞模式
void setSocketNonblock(SOCKET sock);// 设置一个套接字为非阻塞模式
void setSocketNodelay(SOCKET sock);//在套接字上设置NO_DELAY选项,禁止Nagle 算法
3 MatrixSSL实例程序
1证书的生成
与普通的网络通信应用程序不同,基于Matrixssl的程序运行时需要相应的证书和私钥文件实现对客户端和服务器端的身份验证。Matrixssl提供对Openssl格式证书的支持,证书和私钥可以由Openssl应用程序生成。以下是一个证书的生成过程:
1) 创建一个CA证书的私钥和自签署CA证书
生成由DES3加密的RSA私钥文件:OpenSSL genrsa -des3 -out CA.key 1024
使用CA的私钥创建一个自签署的CA证书:OpenSSL req -new -x509 -days 365 -key CA.key -out CA.crt
2)为服务器端创建由CA签署的证书
生成服务器的RSA私钥文件:OpenSSL genrsa -des3 -out server.key 1024
生成服务器的证书请求文件:OpenSSL req -new -key server.key -out server_auth.csr
生成由CA签署的服务器证书文件:OpenSSL x509 -req -days 365 -in server_auth.csr -CA CA.crt -CAkey CA.key -CAcreateserial -out server_auth.cert
3)为客户端创建由CA签署的证书
创建过程与服务器证书生成过程同。
2 应用程序实例
以下是一个简单的基于MatrixSSL的应用程序,说明如何使用封装的套接字在嵌入式系统中实现一个安全的WEB服务器,该程序使用MatrixSSL1.2.4库函数。在Linux下实现过程为:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include sslSocket.h
#define HTTPS_PORT 8001
static char keyfile[] = server.key;
static char certfile[] = server_auth.cert;
static char CAfile[] = CA.crt;
static const char page[] = HTTP/1.0 200 OK
Content-type: text/html
<html><head><title>this is MicroComputer information</title></head>
<body>This is MicroComputer information</body></html> ;
int main(int argc, char **argv)
{
sslConn_t *cp;
sslKeys_t *keys;
SOCKET listenfd, fd;
unsigned char buf[1024];
int ret,status,err,flags;
flags = 0;
char *password;
password=immortalluo;
cp = NULL;
if (matrixSslOpen() < 0) {
fprintf(stderr, matrixSslOpen failed, exiting...);
} //初始化库函数
if (matrixSslReadKeys(&keys, certfile, keyfile, password, CAfile) < 0) {
exit(0);
} //从磁盘文件中读取证书和相关的密钥资料,并使用密码对加密的私钥解密
if ((listenfd = socketListen(HTTPS_PORT, &err)) == INVALID_SOCKET) {
exit(1);
} //在特定的端口上监听客户端的请求
setSocketBlock(listenfd); //将套接字设置为阻塞模式
while(1){
if ((fd = socketAccept(listenfd, &err)) == INVALID_SOCKET) { continue; } //接受一个客户端的请求
if ((ret = sslAccept(&cp, fd, keys, NULL, flags)) != 0) {
socketShutdown(fd);
continue; }//完成握手过程
ret = sslRead(cp, buf, 1024, &status); //读取客户端的请求
if (ret < 0 || status == SSLSOCKET_EOF ||status == SSLSOCKET_CLOSE_NOTIFY){
socketShutdown(cp->fd);
sslFreeConnection(&cp);
continue; } //判断客户端是否请求关闭
ret = sslWrite(cp, page,(int)strlen(page), &status); //向客户端发送静态网页
if (ret < 0) {
socketShutdown(cp->fd);
sslFreeConnection(&cp);
continue;}
sslWriteClosureAlert(cp); //向客户端发送关闭警告
socketShutdown(cp->fd);
sslFreeConnection(&cp);
}
socketShutdown(listenfd);
matrixSslFreeKeys(keys);
matrixSslClose();
}
4 结束语
Matrixssl是一个可定制的小型SSL函数库,具有可移植、可扩展、可裁减的特点,充分满足了嵌入式环境小、特、专、精的特点非常适合在嵌入式系统中提供安全解决方案;但是Matrixssl只支持RSA公钥加密,考虑到效率因素,可在Matrixssl中实现更适合嵌入式环境的ECC公钥加密体制,这是下一步研究目标。
参考文献:
1 SSL 3.0 Specification[EB/OL]. http://wp.netscape.com/eng/ssl3/
2 OpenSSL. The Open Source Toolkit for SSL-TLS[EB/OL]. http://www.openssl.org/
3 PeerSec Networks,“MatrixSSL-Open Source EmbeddedSSL”[EB/OL], http://www.matrixssl.org/