通过 wolfSSL 为 Galileo 上的 Arduino 带来 SSL 支持
本文研究了通过 wolfSSL Inc. 的 wolfSSL 库为在 Galileo 上运行的 Arduino 草图添加 SSL 支持的两种方法。
获取新的 Intel® 物联网开发套件,这是一个完整的软硬件解决方案,让开发人员可以使用 Intel® Galileo 和 Intel® Edison 板创建令人兴奋的新解决方案。请访问 Intel® 物联网开发者中心。
目录
引言
入门
步骤 1:为 Yocto 构建 wolfSSL
步骤 2:在 Galileo 上安装 wolfSSL
步骤 3:修改 Arduino IDE 的编译模式
步骤 4:将 wolfSSL 构建文件安装到 Arduino IDE 系统上
示例草图
注意事项
下载次数
引言
Intel® Galileo 开发板是一款 Arduino*-认证的开发和原型设计板。Galileo 基于 Yocto 1.4 Poky Linux* 版本构建,将 Arduino 开发环境与完整的基于 Linux 的计算机系统相结合,让爱好者能够将 Linux 系统调用和操作系统提供的服务集成到他们的 Arduino 草图中。
Arduino 平台长期存在的一个限制是缺乏 SSL 支持。没有 SSL,基于 Arduino 的设备无法使用 HTTPS 安全地传输数据,因此被迫使用明文 HTTP 进行不安全通信。为了绕过此限制,参与物联网构建的设备必须依赖充当互联网桥梁的辅助设备。Arduino 设备使用 HTTP 与桥梁通信,桥梁再使用 HTTPS 与基于互联网的服务通信。
这种解决方案对于固定网络位置的设备来说效果很好,但它确实需要额外的硬件,并且会引入一个集中点,该集中点本身可能容易受到攻击。对于可能偶尔依赖公共无线网络的移动设备来说,这种方法可能完全不切实际。对连接设备的最佳保护是通过设备本身直接支持 SSL 来实现的。
在 Galileo 上,Arduino 草图只是一个 C++ 程序,它被交叉编译成机器代码,并作为由操作系统管理的进程执行。这意味着它可以访问任何其他已编译程序相同的系统资源,特别是该程序可以链接到任意的已编译库。这里的含义是,添加 SSL 支持就像将 Arduino 草图链接到现有的 SSL 库一样简单。
本文研究了通过 wolfSSL Inc.(以前称为 CyaSSL 库)的 wolfSSL 库为在 Galileo 上运行的 Arduino 草图添加 SSL 支持的两种方法。wolfSSL 库是一个轻量级的 SSL/TLS 库,专为资源受限环境和嵌入式应用程序而设计,并根据 GPLv2 许可证分发。
入门
本文探讨了将 wolfSSL 库链接到 Arduino 草图的两种方法,但它们都遵循相同的基本步骤
- 为 Yocto 构建 wolfSSL
- 将 wolfSSL 共享库安装到您的 Galileo 映像中
- 修改 Galileo 的 Arduino IDE 的编译模式
- 将 wolfSSL 构建文件安装到托管 Arduino IDE 的系统上
此过程复杂度中等,确实需要对 Linux 环境、shell 命令、软件软件包和软件构建过程有扎实的掌握,以及将文件传输到 Linux 系统和从 Linux 系统传输文件的方法。虽然本文在具体的 Linux 命令上进行了一些详细介绍,但它不是一个分步说明手册,它假设读者知道如何在 Linux 系统上操作文件。
这些过程应该适用于 Galileo 和 Galileo 2 主板。
方法 1:动态链接
在动态链接方法中,Arduino 草图与共享对象库 libwolfssl.so 进行动态链接。这种方法对于编程来说最简单,因为草图只需直接调用库函数。
然而,这种方法也存在缺点
- Galileo 的 Arduino IDE 对编译所有草图使用单个配置,因此链接器将在生成的可执行文件中放置对 libwolfssl.so 的引用,而不管草图是否需要它。如果目标 Galileo 系统上安装了 wolfSSL 库,这不成问题,但如果任何草图被编译到另一个 *不* 包含该库的系统上,那么这些草图将无法执行。
- 托管 Galileo 的 Arduino IDE 的系统必须将交叉编译的 wolfSSL 库安装到 Arduino IDE 构建树中。
方法 2:动态加载
在动态加载方法中,Arduino 草图与动态链接加载器库 libdl 进行链接。wolfSSL 库及其符号在执行过程中通过 dlopen() 和 dlsym() 动态加载。这种方法编程起来比较繁琐,因为函数名不能直接由链接器解析,必须由代码显式加载并保存为函数指针。
与动态链接方法相比的优点是
- libdl 是 Galileo SD 卡映像的一部分,因此经过修改的 IDE 编译的任意草图仍然可以在其他 Galileo 系统上运行。
- 托管 Galileo 的 Arduino IDE 的系统只需要将 wolfSSL 头文件安装到构建树中。
- 有了这个单一的修改,*任何*动态库都可以供 Arduino 草图使用。
步骤 1:为 Yocto 构建 wolfSSL
将 SSL 添加到 Arduino 环境的第一步是使用 uClibc 作为 C 库为 Yocto 构建 wolfSSL 库。这通过 Intel 的 Arduino IDE for Linux 随附的交叉编译器来实现。*必须在 Linux 系统上执行此步骤。*
自 Galileo 发布以来,IDE 已发布了多个版本,任何版本都可以,但由于不同版本之间的路径名称已更改,本文档假定您将使用最新版本,即 Intel 捆绑包版本 1.0.4 和 Arduino IDE 版本 1.6.0。
软件存档 |
http://www.intel.com/content/www/us/en/do-it-yourself/downloads-and-documentation.html |
目标文件 |
Arduino 软件 1.6.0 - Intel 1.0.4 for Linux |
选择 32 位或 64 位存档,取决于您的 Linux 发行版。
配置交叉编译器
如果您已经使用此版本的 IDE 为您的 Galileo 设备构建了草图,那么它应该已经正确配置,您可以跳过此任务。
如果您尚未构建草图,则需要运行安装脚本以正确设置软件包配置文件中的路径名称。此脚本 install_script.sh 位于 IDE 包根目录下的 hardware/tools/i586 目录中。运行它时不带任何参数
~/galileo/arduino-1.6.0+Intel/hardware/tools/i586$ ./install_script.sh Setting it up.../tmp/tmp.7FGQfwEaNz/relocate_sdk.sh /nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/relocate_sdk.sh link:/nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2 link:/nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/x86_64-pokysdk-linux/lib/libpthread.so.0 link:/nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/x86_64-pokysdk-linux/lib/libnss_compat.so.2 link:/nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/x86_64-pokysdk-linux/lib/librt.so.1 link:/nfs/common/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/x86_64-pokysdk-linux/lib/libresolv.so.2 … SDK has been successfully set up and is ready to be used.
现在,交叉编译器已准备好使用。
下载 wolfSSL 源码
要为 Galileo 构建 wolfSSL 库,您需要从 wolfSSL Inc. 下载源代码。截至目前,最新版本是 3.4.0,分发为 Zip 存档。将源代码解压到您选择的目录中。
构建库
为了构建库,您必须首先设置您的 shell 环境以引用交叉编译器。环境设置文件假定为 Bourne shell 环境,因此您必须在适当且兼容的 shell(如 sh 或 bash)中执行这些步骤。强烈建议从干净的 shell 环境开始。
首先,从 Intel Arduino IDE 中 sourcing 环境设置文件。请务必使用您的 Intel Arduino IDE 的路径,而不是示例中给出的路径
~/src/wolfssl-3.4.0$ . ~/galileo/arduino-1.6.0+Intel/hardware/tools/i586/environment-setup-i586-poky-linux-uclibc
此步骤不会产生任何输出。
现在,您可以运行 wolfSSL 的 configure 脚本了。有必要向 configure 提供一些选项,以便正确地初始化它以进行交叉编译。
~/src/wolfssl-3.4.0$ ./configure --prefix=$HOME/wolfssl --host=i586-poky-linux-uclibc \ --target=i586-poky-linux-uclibc
请注意,您必须为 configure 脚本提供绝对路径,并且不能使用 ~ 作为主目录的快捷方式。请改用 $HOME shell 变量。
--prefix 选项告诉构建系统在哪里安装库。由于您实际上不会在此系统上安装库,任何目录都可以。此示例显示它安装在 $HOME/wolfssl 中。
--host 和 --target 选项告诉构建系统这将是交叉编译,目标架构标识为 i586-poky-linux-uclibc。
configure 脚本将生成大量输出。当它完成时,假设没有错误,您可以使用“make”来构建软件。
~/src/wolfssl-3.4.0$ make make[1]: Entering directory `/nfs/users/johnm/src/wolfssl-3.4.0' CC wolfcrypt/test/testsuite_testsuite_test-test.o CC examples/client/testsuite_testsuite_test-client.o CC examples/server/testsuite_testsuite_test-server.o CC examples/client/tests_unit_test-client.o CC examples/server/tests_unit_test-server.o CC wolfcrypt/src/src_libwolfssl_la-hmac.lo CC wolfcrypt/src/src_libwolfssl_la-random.lo … CCLD examples/client/client CCLD examples/echoserver/echoserver CCLD testsuite/testsuite.test CCLD tests/unit.test make[1]: Leaving directory `/nfs/users/johnm/src/wolfssl-3.4.0'
然后通过“make install”将其安装到本地/临时位置
~/src/wolfssl-3.4.0$ make install
您的库现在将在您为 configure 的 --prefix 选项指定的目录中,位于 lib 子目录中
~/src/wolfssl-3.4.0$ cd $HOME/wolfssl/lib ~/wolfssl/lib$ ls -CFs total 188 4 libwolfssl.la* 0 libwolfssl.so.0@ 4 pkgconfig/ 0 libwolfssl.so@ 180 libwolfssl.so.0.0.0*
现在您可以将 wolfSSL 库安装到 Galileo 了。
步骤 2:在 Galileo 上安装 wolfSSL
有两种通用的方法可以将 wolfSSL 包安装到 Galileo:第一种是直接将文件复制到 Galileo 文件系统映像,第二种是通过网络连接将文件复制到正在运行的 Galileo 系统上。但无论哪种情况,您都需要知道您在系统上运行的是*哪个*映像,是 SD 卡 Linux 映像,还是物联网开发套件映像。
对于运行 SD 卡 Linux 映像的 Galileo
SD 卡 Linux 映像是 Galileo 板的原始系统映像。它是一个非常最小化的系统映像,大小不到 312 MB。它缺少开发工具(例如,没有编译器)和高级 Linux 实用程序。截至目前,SD 卡映像的最新版本是 1.0.4。
软件存档 |
http://www.intel.com/content/www/us/en/do-it-yourself/downloads-and-documentation.html |
目标文件 |
SD 卡 Linux 映像 (SDCard.1.0.4.tar.bz2) |
下面讨论了两种安装方法,但直接安装到 Galileo 文件系统映像是首选,因为您可以获得更强大的工具。
将 wolfSSL 安装到文件系统映像
这种方法比另一种更容易,出错的可能性也更小,因为您可以使用文件同步工具,并且没有网络带来的额外复杂性。只需将 Galileo 文件系统映像挂载为构建机上的文件系统,然后您就可以使用 rsync 将 wolfSSL 包复制到位。您可以将此文件复制到您的构建系统,或者使用读卡器直接在您的 Linux 系统上挂载带有映像的 microSD 卡。
在 Galileo SD 卡文件系统树中,主 Galileo 文件系统映像名为 image-full-galileo-clanton.ext3,可以使用 loop 设备挂载。在您的构建系统上创建一个挂载点(目录)——下面的示例使用 /mnt/galileo——然后使用 mount 命令挂载它
~/wolfssl$ cd /mnt /mnt$ sudo mkdir galileo /mnt$ mount –t ext3 –o loop /path/to/image-full-galileo-clanton.ext3 /mnt/galileo
现在 Galileo 文件系统应该可以在 /mnt/galileo 下看到。
使用 rsync 将共享库及其符号链接复制到位。它们应该安装在 Galileo 系统的 /usr/lib 中
/mnt$ rsync –a $HOME/wolfssl/lib/lib* /mnt/galileo/usr/lib
请确保将 $HOME/wolfSSL 替换为您本地 wolfSSL 构建的实际位置。
通过网络安装 wolfSSL
对于此方法,Galileo 系统必须已启动并运行,并具有活动的网络连接,您需要知道其 IP 地址。由于 Galileo 缺少 rsync 等文件同步实用程序,因此文件必须使用 tar 复制以确保符号链接得到正确处理。
首先,使用 cd 切换到本地 wolfSSL 构建的 lib 子目录。
~/wolfssl$ cd $HOME/wolfssl/lib
现在使用 tar 创建共享库及其符号链接的存档,并使用 scp 将其复制到 Galileo。
~/wolfssl/lib$ tar cf /tmp/wolfssl.tar lib* ~/wolfssl/lib$ cd /tmp /tmp$ scp wolfssl.tar root@192.168.1.2:/tmp root@192.168.1.2’s password:
请确保输入您的 Galileo 的 IP 地址而不是示例。
现在登录到您的 Galileo 设备并解压存档
/tmp$ ssh root@192.168.1.2 root@192.168.1.2’s password: root@clanton:~# cd /usr/lib root@clanton:/usr/lib# tar xf /tmp/wolfssl.tar
对于运行物联网开发套件映像的 Galileo
物联网开发套件映像是一个更大、更传统的 Linux 系统映像,其中包括开发工具和许多有用的系统实用程序和守护进程。它被分发为一个原始磁盘映像,其中包含 FAT32 和 ext3 磁盘分区,并且必须直接写入 SD 卡。
软件存档 |
|
目标文件 |
iotdk-galileo-image.bz2 |
下面讨论了两种安装方法。
截至目前,*您还需要将开发套件映像上的 uClibc 库替换为您 Intel Arduino IDE 附带的那个*。由于这两个库的构建过程存在差异,并非 IDE 版本中导出的所有符号都存在于开发套件版本中,这可能导致 Arduino 草图运行时崩溃。特别是 wolfSSL 库,它引入了对开发套件的 uClibc 构建中缺少的其中一个符号的依赖,如果您不替换 Galileo 系统上的库,尝试使用 libwolfssl 将会失败。
将 wolfSSL 安装到文件系统映像
如果将 SD 卡读卡器连接到您的 Linux 系统,则此方法最容易。由于开发套件映像包含 ext3 分区,大多数 Linux 发行版会自动为您挂载它,通常在* /media* 或* /mnt* 下。使用 df 命令和 -T 选项来帮助您确定挂载点。
~$ df -T | grep ext3 /dev/sde2 ext3 991896 768032 172664 82% /media/johnm/048ce1b1-be13-4a5d-8352-2df03c0d9ed8
在这种情况下,挂载点是* /media/johnm/048ce1b1-be13-4a5d-8352-2df03c0d9ed8*
~$ /bin/ls -CFs /media/johnm/048ce1b1-be13-4a5d-8352-2df03c0d9ed8 total 96 4 bin/ 4 home/ 4 media/ 4 proc/ 4 sys/ 4 www/ 4 boot/ 4 lib/ 4 mnt/ 4 run/ 4 tmp/ 4 dev/ 4 lib32/ 4 node_app_slot/ 4 sbin/ 4 usr/ 4 etc/ 16 lost+found/ 4 opt/ 4 sketch/ 4 var/
Arduino 草图使用的库保存在* /lib32* 中。使用 cd 切换到该目录,然后使用 rsync 将 wolfSSL 共享库及其符号链接复制到该目录,以保留符号链接。
~/wolfssl$ cd /path-to-mountpoint/lib32 lib32$ rsync –a $HOME/wolfssl/lib/lib* .
请确保将*path-to-mountpoint*替换为您的 SD 卡 Galileo 文件系统的实际挂载点。
现在,您需要用 Intel Arduino IDE 的那个替换开发套件的 uClibc 库。与其删除或覆盖它,不如执行以下过程,只需重命名它,从而有效地禁用原始库的副本,而无需永久删除它(这也将防止当前运行的草图崩溃)
lib32$ mv libuClibc-0.9.34-git.so libuClibc-0.9.34-git.so.dist lib32$ cp ~/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/i586-poky-linux-uclibc/lib/libuClibc-0.9.34-git.so .
请记住使用您 Intel Arduino IDE 的实际路径替换示例路径。
通过网络安装 wolfSSL
对于此方法,Galileo 系统必须已启动并运行,并具有活动的网络连接,您需要知道其 IP 地址。由于 Galileo 缺少 rsync 等文件同步实用程序,因此文件必须使用 tar 复制以确保符号链接得到正确处理。
首先,使用 cd 切换到本地 wolfSSL 构建的 lib 子目录。
~/wolfssl$ cd $HOME/wolfssl/lib
现在使用 tar 创建共享库及其符号链接的存档,并使用 scp 将其复制到 Galileo。
~/wolfssl/lib$ tar cf /tmp/wolfssl.tar lib* ~/wolfssl/lib$ cd /tmp /tmp$ scp wolfssl.tar root@192.168.1.2:/tmp root@192.168.1.2’s password:
请确保输入您的 Galileo 的 IP 地址而不是示例。
现在登录到您的 Galileo 设备并解压存档
/tmp$ ssh root@192.168.1.2 root@192.168.1.2’s password: root@quark:~# cd /lib32 root@quark:/lib32# tar xf /tmp/wolfssl.tar
接下来,您需要用 Intel Arduino IDE 的那个替换开发套件的 uClibc 库。与其删除或覆盖它,不如执行以下过程,只需重命名它,从而有效地禁用原始库的副本,而无需永久删除它(这也将防止当前运行的草图崩溃)
root@quark:/lib32$ mv libuClibc-0.9.34-git.so libuClibc-0.9.34-git.so.dist
从您的 Galileo 系统注销,并使用 scp 将库从您的 Intel Arduino IDE 复制到您的 Galileo
~$ scp ~/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/i586-poky-linux-uclibc/lib/libuClibc-0.9.34-git.so root@192.168.1.2:/lib32
请记住使用您 Intel Arduino IDE 的实际路径替换示例路径,并使用您的 Galileo 的 IP 地址。
步骤 3:修改 Arduino IDE 的编译模式
要编译想要使用 wolfSSL 库的草图,您需要修改 Galileo 的 Arduino IDE 的编译模式。必要的特定修改取决于您选择的链接 libwolfssl 的方法,但无论哪种方法,编译模式都位于*hardware/intel/i586-uclibc* 中,适用于 Intel 1.0.4 及更高版本的 Arduino IDE 1.5.3。
修改编译模式
保存编译模式的文件名为 platform.txt。
您将编辑“recipe.c.combine.pattern
”这一行,它看起来像这样
## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -march={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm -lpthread
动态链接
如果您使用动态链接方法,那么您需要告诉链接器在链接可执行文件时将 libwolfssl 添加到库列表中。在行末添加 -lwolfssl。
## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -march={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm –lpthread -lwolfssl
请确保不要添加任何换行符。
动态加载
在动态加载方法中,您需要告诉链接器将动态加载器库添加到库列表中。在行末添加 -ldl。
## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -march={build.mcu} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm -ldl
请确保不要添加任何换行符。
步骤 4:将 wolfSSL 构建文件安装到 Arduino IDE 系统上
在编译草图之前的最后一步是将 wolfSSL 构建文件安装到 Galileo 的 Arduino IDE 构建树中。对于 1.6.0 版本,构建树位于*hardware/tools/i586/i586-poky-linux-uclibc*。在那里,您会找到一个类 UNIX 的目录结构,其中包含 etc、lib、usr 和 var 目录。
安装 wolfSSL 头文件
无论您使用动态加载还是动态链接方法,您都需要将 wolfSSL 头文件安装到 Arduino IDE 可以找到的地方,以便您可以在草图中包含它们
#include <wolfssl/ssl.h>
您可以在您在步骤 1 中创建的本地 wolfSSL 安装中找到头文件,位于 include 子目录中。出于向后兼容的原因,wolfSSL 发行版包含 include/cyassl 和 include/wolfssl 中的头文件。
wolfSSL 头文件必须安装到 usr/include
安装 wolfSSL 库
如果您使用的是动态链接方法,那么您还必须将交叉编译的库安装到 usr/lib。*如果您使用的是动态加载方法,则可以跳过此步骤。*
库位于在步骤 1 中创建的本地安装中,位于 lib 目录中。从那里复制
libwolfssl.la libwolfssl.so libwolfssl.so.*
除了一个共享对象文件外,其余的都是符号链接,但将它们作为常规文件复制也可以。
示例草图
以下示例草图展示了如何使用动态链接和动态加载方法与 wolfSSL 库进行交互。它们执行相同的函数:连接到目标 Web 服务器并使用 SSL 获取网页。页面源代码会打印到 Galileo 的 Arduino IDE 的串行控制台。
这些草图已根据Intel 示例源代码许可协议获得许可。除了在此处浏览源代码外,您还可以直接下载它们。
注意:请务必更改服务器名称,并在必要时更改要获取的页面 URL。
动态链接示例
/*
Copyright 2015 Intel Corporation All Rights Reserved.
The source code, information and material ("Material") contained herein is owned
by Intel Corporation or its suppliers or licensors, and title to such Material
remains with Intel Corporation or its suppliers or licensors. The Material
contains proprietary information of Intel or its suppliers and licensors. The
Material is protected by worldwide copyright laws and treaty provisions. No part
of the Material may be used, copied, reproduced, modified, published, uploaded,
posted, transmitted, distributed or disclosed in any way without Intel's prior
express written permission. No license under any patent, copyright or other
intellectual property rights in the Material is granted to or conferred upon
you, either expressly, by implication, inducement, estoppel or otherwise. Any
license under such intellectual property rights must be express and approved by
Intel in writing.
Include any supplier copyright notices as supplier requires Intel to use.
Include supplier trademarks or logos as supplier requires Intel to use,
preceded by an asterisk. An asterisked footnote can be added as follows: *Third
Party trademarks are the property of their respective owners.
Unless otherwise agreed by Intel in writing, you may not remove or alter this
notice or any other notice embedded in Materials by Intel or Intel's suppliers
or licensors in any way.
*/
#include <LiquidCrystal.h>
#include <dlfcn.h>
#include <wolfssl/ssl.h>
#include <Ethernet.h>
#include <string.h>
const char server[]= "www.example.com"; // Set this to a web server of your choice
const char req[]= "GET / HTTP/1.0\r\n\r\n"; // Get the root page
int repeat;
int wolfssl_init ();
int client_send (WOLFSSL *, char *, int, void *);
int client_recv (WOLFSSL *, char *, int, void *);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void *handle;
EthernetClient client;
WOLFSSL_CTX *ctx= NULL;
WOLFSSL *ssl= NULL;
WOLFSSL_METHOD *method= NULL;
void setup() {
Serial.begin(9600);
Serial.println("Initializing");
lcd.begin(16,2);
lcd.clear();
if ( wolfssl_init() == 0 ) goto fail;
Serial.println("OK");
// Set the repeat count to a maximum of 5 times so that we aren't
// fetching the same URL over and over forever.
repeat= 5;
return;
fail:
Serial.print("wolfSSL setup failed");
repeat= 0;
}
int wolfssl_init ()
{
char err[17];
// Create our SSL context
method= wolfTLSv1_2_client_method();
ctx= wolfSSL_CTX_new(method);
if ( ctx == NULL ) return 0;
// Don't do certification verification
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
// Specify callbacks for reading to/writing from the socket (EthernetClient
// object).
wolfSSL_SetIORecv(ctx, client_recv);
wolfSSL_SetIOSend(ctx, client_send);
return 1;
}
int client_recv (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)
{
int i= 0;
// Read a byte while one is available, and while our buffer isn't full.
while ( client.available() > 0 && i < sz) {
buf[i++]= client.read();
}
return i;
}
int client_send (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)
{
int n= client.write((byte *) buf, sz);
return n;
}
void loop() {
char errstr[81];
char buf[256];
int err;
// Repeat until the repeat count is 0.
if (repeat) {
if ( client.connect(server, 443) ) {
int bwritten, bread, totread;
Serial.print("Connected to ");
Serial.println(server);
ssl= wolfSSL_new(ctx);
if ( ssl == NULL ) {
err= wolfSSL_get_error(ssl, 0);
wolfSSL_ERR_error_string_n(err, errstr, 80);
Serial.print("wolfSSL_new: ");
Serial.println(errstr);
}
Serial.println(req);
bwritten= wolfSSL_write(ssl, (char *) req, strlen(req));
Serial.print("Bytes written= ");
Serial.println(bwritten);
if ( bwritten > 0 ) {
totread= 0;
while ( client.available() || wolfSSL_pending(ssl) ) {
bread= wolfSSL_read(ssl, buf, sizeof(buf)-1);
totread+= bread;
if ( bread > 0 ) {
buf[bread]= '\0';
Serial.print(buf);
} else {
Serial.println();
Serial.println("Read error");
}
}
Serial.print("Bytes read= ");
Serial.println(bread);
}
if ( ssl != NULL ) wolfSSL_free(ssl);
client.stop();
Serial.println("Connection closed");
}
--repeat;
}
// Be polite by sleeping between iterations
delay(5000);
}
动态加载示例
/*
Copyright 2015 Intel Corporation All Rights Reserved.
The source code, information and material ("Material") contained herein is owned
by Intel Corporation or its suppliers or licensors, and title to such Material
remains with Intel Corporation or its suppliers or licensors. The Material
contains proprietary information of Intel or its suppliers and licensors. The
Material is protected by worldwide copyright laws and treaty provisions. No part
of the Material may be used, copied, reproduced, modified, published, uploaded,
posted, transmitted, distributed or disclosed in any way without Intel's prior
express written permission. No license under any patent, copyright or other
intellectual property rights in the Material is granted to or conferred upon
you, either expressly, by implication, inducement, estoppel or otherwise. Any
license under such intellectual property rights must be express and approved by
Intel in writing.
Include any supplier copyright notices as supplier requires Intel to use.
Include supplier trademarks or logos as supplier requires Intel to use,
preceded by an asterisk. An asterisked footnote can be added as follows: *Third
Party trademarks are the property of their respective owners.
Unless otherwise agreed by Intel in writing, you may not remove or alter this
notice or any other notice embedded in Materials by Intel or Intel's suppliers
or licensors in any way.
*/
#include <dlfcn.h>
#include <wolfssl/ssl.h>
#include <Ethernet.h>
#include <string.h>
/*
Set this to the location of your wolfssl shared library. By default you
shouldn't need to specify a path unless you put it somewhere other than
/usr/lib (SD-Card image) or /lib32 (IoT Developer Kit image).
*/
#define WOLFSSL_SHLIB_PATH "libwolfssl.so"
const char server[]= "www.example.com"; // Set this to a web server of your choice
const char req[]= "GET / HTTP/1.0\r\n\r\n"; // Get the root page
int repeat;
int wolfssl_dlload ();
int wolfssl_init ();
int client_send (WOLFSSL *, char *, int, void *);
int client_recv (WOLFSSL *, char *, int, void *);
void *handle;
EthernetClient client;
WOLFSSL_CTX *ctx= NULL;
WOLFSSL *ssl= NULL;
WOLFSSL_METHOD *method= NULL;
typedef struct wolfssl_handle_struct {
WOLFSSL_METHOD *(*wolfTLSv1_2_client_method)();
WOLFSSL_CTX *(*wolfSSL_CTX_new)(WOLFSSL_METHOD *);
void (*wolfSSL_CTX_set_verify)(WOLFSSL_CTX *, int , VerifyCallback);
int (*wolfSSL_connect)(WOLFSSL *);
int (*wolfSSL_shutdown)(WOLFSSL *);
int (*wolfSSL_get_error)(WOLFSSL *, int);
void (*wolfSSL_ERR_error_string_n)(unsigned long, char *, unsigned long);
WOLFSSL *(*wolfSSL_new)(WOLFSSL_CTX *);
void (*wolfSSL_free)(WOLFSSL *);
void (*wolfSSL_SetIORecv)(WOLFSSL_CTX *, CallbackIORecv);
void (*wolfSSL_SetIOSend)(WOLFSSL_CTX *, CallbackIORecv);
int (*wolfSSL_read)(WOLFSSL *, void *, int);
int (*wolfSSL_write)(WOLFSSL *, void *, int);
int (*wolfSSL_pending)(WOLFSSL *);
} wolfssl_t;
wolfssl_t wolf;
void setup() {
Serial.begin(9600);
Serial.println("Initializing");
if ( wolfssl_dlload() == 0 ) goto fail;
if ( wolfssl_init() == 0 ) goto fail;
// Set the repeat count to a maximum of 5 times so that we aren't
// fetching the same URL over and over forever.
repeat= 5;
return;
fail:
Serial.print("wolfSSL setup failed");
repeat= 0;
}
int wolfssl_init ()
{
char err[17];
// Create our SSL context
method= wolf.wolfTLSv1_2_client_method();
ctx= wolf.wolfSSL_CTX_new(method);
if ( ctx == NULL ) return 0;
// Don't do certification verification
wolf.wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
// Specify callbacks for reading to/writing from the socket (EthernetClient
// object).
wolf.wolfSSL_SetIORecv(ctx, client_recv);
wolf.wolfSSL_SetIOSend(ctx, client_send);
return 1;
}
int wolfssl_dlload ()
{
// Dynamically load our symbols from libwolfssl.so
char *err;
// goto is useful for constructs like this, where we need everything to succeed or
// it's an overall failure and we abort. If just one of these fails, print an error
// message and return 0.
handle= dlopen(WOLFSSL_SHLIB_PATH, RTLD_NOW);
if ( handle == NULL ) {
err= dlerror();
goto fail;
}
wolf.wolfTLSv1_2_client_method= (WOLFSSL_METHOD *(*)()) dlsym(handle, "wolfTLSv1_2_client_method");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_CTX_new= (WOLFSSL_CTX *(*)(WOLFSSL_METHOD *)) dlsym(handle, "wolfSSL_CTX_new");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_CTX_set_verify= (void (*)(WOLFSSL_CTX* , int , VerifyCallback)) dlsym(handle, "wolfSSL_CTX_set_verify");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_connect= (int (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_connect");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_get_error= (int (*)(WOLFSSL *, int)) dlsym(handle, "wolfSSL_get_error");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_ERR_error_string_n= (void (*)(unsigned long, char *, unsigned long)) dlsym(handle, "wolfSSL_ERR_error_string_n");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_new= (WOLFSSL *(*)(WOLFSSL_CTX *)) dlsym(handle, "wolfSSL_new");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_free= (void (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_free");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_SetIORecv= (void (*)(WOLFSSL_CTX *, CallbackIORecv)) dlsym(handle, "wolfSSL_SetIORecv");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_SetIOSend= (void (*)(WOLFSSL_CTX *, CallbackIORecv)) dlsym(handle, "wolfSSL_SetIOSend");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_read= (int (*)(WOLFSSL *, void *, int)) dlsym(handle, "wolfSSL_read");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_write= (int (*)(WOLFSSL *, void *, int)) dlsym(handle, "wolfSSL_write");
if ( (err= dlerror()) != NULL ) goto fail;
wolf.wolfSSL_pending= (int (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_pending");
if ( (err= dlerror()) != NULL ) goto fail;
Serial.println("OK");
return 1;
fail:
Serial.println(err);
return 0;
}
int client_recv (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)
{
int i= 0;
// Read a byte while one is available, and while our buffer isn't full.
while ( client.available() > 0 && i < sz) {
buf[i++]= client.read();
}
return i;
}
int client_send (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)
{
int n= client.write((byte *) buf, sz);
return n;
}
void loop() {
char errstr[81];
char buf[256];
int err;
// Repeat until the repeat count is 0.
if (repeat) {
if ( client.connect(server, 443) ) {
int bwritten, bread, totread;
Serial.print("Connected to ");
Serial.println(server);
ssl= wolf.wolfSSL_new(ctx);
if ( ssl == NULL ) {
err= wolf.wolfSSL_get_error(ssl, 0);
wolf.wolfSSL_ERR_error_string_n(err, errstr, 80);
Serial.print("wolfSSL_new: ");
Serial.println(errstr);
}
Serial.println(req);
bwritten= wolf.wolfSSL_write(ssl, (char *) req, strlen(req));
Serial.print("Bytes written= ");
Serial.println(bwritten);
if ( bwritten > 0 ) {
totread= 0;
while ( client.available() || wolf.wolfSSL_pending(ssl) ) {
bread= wolf.wolfSSL_read(ssl, buf, sizeof(buf)-1);
totread+= bread;
if ( bread > 0 ) {
buf[bread]= '\0';
Serial.print(buf);
} else {
Serial.println();
Serial.println("Read error");
}
}
Serial.print("Bytes read= ");
Serial.println(totread);
}
if ( ssl != NULL ) wolf.wolfSSL_free(ssl);
client.stop();
Serial.println("Connection closed");
}
--repeat;
}
// Be polite by sleeping between iterations
delay(5000);
}
注意事项
本文档中的信息是与 Intel 产品相关提供的。本文档不授予任何知识产权的明示或暗示、禁止反言或其他许可。除 Intel 对此类产品的销售条款和条件另有规定外,Intel 对此不承担任何责任,并声明对销售和/或使用 Intel 产品的任何明示或暗示的保证,包括对特定用途的适用性、适销性或对任何专利、版权或其他知识产权的侵权的保证。
除非 Intel 书面同意,否则 Intel 产品不设计也不用于任何可能导致人员伤亡的应用程序。
Intel 可随时修改规格和产品描述,恕不另行通知。设计人员不得依赖任何标记为“保留”或“未定义”的特性或指令的缺失或特性。Intel 保留这些以供将来定义,并且对于因将来修改而引起的任何冲突或不兼容性不承担任何责任。此处的信息如有变更,恕不另行通知。请勿以此信息最终确定设计。
本文档中描述的产品可能包含已知为勘误的设计缺陷或错误,这可能导致产品偏离已发布的规范。当前的已表征勘误可应要求提供。
请联系您当地的英特尔销售办事处或您的经销商以获取最新的规范,并在下订单前进行咨询。
可以通过致电 1-800-548-4725 或访问:http://www.intel.com/design/literature.htm 获取本文档中引用的具有订购号的文档副本或其他 Intel 文献。
Intel、Intel 徽标、VTune、Cilk 和 Xeon 是 Intel Corporation 在美国和其他国家/地区的商标。
*其他名称和品牌可能被声明为他方财产
版权© 2012 Intel Corporation。保留所有权利。
立即开始创新!Intel® 物联网开发者计划提供知识、工具、套件以及专家社区,助您快速轻松地将您的创新想法转化为物联网解决方案。
使用 Intel® 物联网开发套件(适用于 Intel® Edison 和 Intel® Galileo 平台)梦想它,构建它。这些套件是通用、性能优化且完全集成的端到端物联网解决方案,支持各种编程环境、工具、安全、云连接和硬件。
如需更多资源并了解新的 Intel® 物联网开发者套件 v1.0 如何帮助您简化物联网项目
- 下载 Intel® 物联网开发者套件
- 访问 Intel® 物联网开发者中心
- 参加我们的 Roadshows,获取创建您自己的物联网项目的实践培训