本文的核心是讲怎么把项目中的openssl库替换成wolfssl库,并且尽可能的少改工程代码。
一、为什么选择wolfssl替换已有的openssl库
- wolfssl比较小。
要从工程中移除openssl的最主要的一个原因是openssl太大了。在嵌入式工程中,为了实现一个小的功能,引用了一个openssl,编译生成的固件太大了,flash装不下了。而wolfssl在满足基本需求的同时,又能大大减小固件的大小。 - wolfssl性能相对优秀。
和openssl对比,wolfssl的性能更加优秀,关于openssl和wolfssl的对比,可从wolfssl官网得到详尽的答案:openssl和wolfssl的特点对比 - wolfssl方便移植。
wolfssl 除了本地API之外,wolfssl还提供了一个openssl兼容性头文件wolfssl/openssl/ssl.h ,以简化转换为使用wolfssl或帮助将现有的openssl应用程序移植到wolfssl。openssl兼容层将最常用的openssl命令的子集映射到wolfssl的本地API函数。这应该允许在应用程序或项目中通过wolfssl轻松替换openssl,而无需更改大量代码。
二、如何编译安装wolfssl
首先需要去官网下载安装包:wolfssl下载
或者去github上下载:wolfssl下载
学习资料和论坛都在官网上可以找到,这是wolfssl的使用手册
在PC linux系统编译:
- ./configure
- make
- sudo make install
./configure后面可以跟很多选项,比如指明编译链、安装路径、静态库或者动态库等。具体说明可以执行 ./configure –help
官方关于configure的说明参考:configure –help 说明链接
交叉编译链编译:
需要用–host选项来指明交叉编译链。
./configure --prefix=$PWD/output --host=arm-linux --enable-openssh --enable-static --disable-shared
需要注意的是交叉编译链路径需要加入到PATH环境变量中,不然也是找不到的。
执行configure的目的是为了生成Makefile。需要确保在当前路径有output目录,这是通过–prefix决定的,不指定将默认安装在/usr/local目录下。生成的libwolfssl.a 静态库放到工程代码中,然后修改相关Makefile将库包含进来。并且在源码中需要包含头文件
三、移植过程遇到的问题
出现如下错误信息,找不到库:
./echoserver: error while loading shared libraries: libwolfssl.so.16: cannot open shared object file: No such file or directory
有以下几种解决方法:
- 第一种方法 最佳解决方法:
因为编译开源库是默认配置安装的,所以库的路径在/usr/local/lib/下,需要软链接到系统能找到库的地方,也就是系统默认库路径下
sudo ln -s /usr/local/lib/libwolfssl.so.16.0.0 /usr/lib/libwolfssl.so.16
- 第二种方法
在configure阶段用–prefix参数把安装目录指定到/usr目录下,会在/usr/include和/usr/local/lib/下生成头文件和库
例如:./configure –prefix=/usr - 第三种方法
针对没有root权限的情况,大多数情况都是执行:
export LD_LIBRARY_PATH=/yourlocalpath:$LD_LIBRARY_PATH - 第四种方法
可以直接加上路径名或者以 -L,-l 指定库
gcc编译时库的依赖顺序经常出现问题:
静态库经常会出现依赖顺序问题,动态库则不会。
当A库依赖于B库时(A库引用B库的函数时,应该写在前面)则在编译的时候链接顺序应该是 -lA -lB 。
虽然提供了兼容层,但是wolfssl的机制和openssl的机制还是有些不同。尝试移植wolfssl库到嵌入式板子。移植后,写的demo程序在板子上可以运行,嵌入到工程中也没有问题。但是,移植到“发送邮件“ 那部分代码,ssl_connect函数连接远程服务器不成功。发现wolfssl和openssl在证书验证机制上是有区别的。wolfssl 客户端默认需要加载证书,而openssl则不用。这意味着如果没有加载CA来验证服务器,则会出现连接错误。官网说可以调用SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0) 来模拟openssl的行为,但这将降低安全性。经过反复试验,还是连接不上。 可能客户端还是需要加载证书。看了一些wolfssl例子,客户端都是需要加载数字证书的。如果是这样的情形,那对应每种类型的邮箱所要加载的证书也不一样(如qq和163),用户绑定的邮箱种类也不可能全部一样,处理起来将会变得很麻烦。 由于目前移植存在风险,所以还是用原来的openssl库。 这是目前遗留的问题,后续再看看。
四、服务器代码
用简单的例子来模拟,可用抓包软件研究一下。
OPEN_SSL宏来控制是否要加入wolfssl机制。客户端和服务器都是不需要加载证书的,因为客户端使用了SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0) 函数。
//server_echo.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>