A PDF version of this article, as well as a zip archive of the code samples, are available in the downloads section, below.
Contents
Introduction
Getting Started
Step 1: Building wolfSSL for Yocto
Step 2: Installing wolfSSL On Galileo
Step 3: Modifying the Compile Patterns for the Arduino IDE
Step 4: Installing the wolfSSL Build Files on the Arduino IDE System
Example Sketches
Notices
Downloads
Introduction
The Intel® Galileo development board is an Arduino*-certified development and prototyping board. Built on the Yocto 1.4 Poky Linux* release, Galileo merges an Arduino development environment with a complete Linux-based computer system allowing enthusiasts to incorporate Linux system calls and OS-provided services in their Ardunio sketches.
One long-standing limitation in the Arduino platform has been a lack of SSL support. Without SSL Arduino-based devices are incapable of securely transmitting data using HTTPS, and are thus forced to communicate insecurely using plain HTTP. In order to work around this limitation, devices that participate in the build out of the Internet of Things must rely on secondary devices which serve as bridges to the internet. The Arduino device communicates using HTTP to the bridge, which in turn communicates to the internet-based service using HTTPS.
This solution works well for devices that have a fixed network location, but it does require additional hardware and introduces a concentration point for multiple devices that itself may be vulnerable to attack. For mobile devices that may occasionally rely on public wireless networks, this approach can be entirely impractical. The best level of protection for connected devices is achieved with SSL support directly on the device itself.
On Galileo an Arduino sketch is just a C++ program that is cross-compiled into machine code and executed as a process that is managed by the operating system. That means that it has access to the same system resources as any other compiled program, and specifically that program can be linked against arbitrary, compiled libraries. The implication here is that adding SSL support is as simple as linking the Arduino sketch to an existing SSL library.
This paper examines two methods for adding SSL support to Arduino sketches running on Galileo via the wolfSSL library from wolfSSL, Inc.* (formerly named the CyaSSL library). The wolfSSL library is a lightweight SSL/TLS library that is designed for resource-constrained environments and embedded applications, and is distributed under the GPLv2 license.
This paper looks at two methods for linking the wolfSSL library to an Arduino sketch, but both of them follow the same basic steps:
- Build wolfSSL for Yocto
- Install the wolfSSL shared library onto your Galileo image
- Modify the compile patterns for the Arduino IDE for Galileo
- Install the wolfSSL build files onto the system hosting the Arduino IDE
This procedure is moderately complex and does require a firm grasp of the Linux environment, shell commands, software packages and software build procedures, as well as methods of transferring files to and from a Linux system. While this paper does go into some detail on specific Linux commands, it is not a step-by-step instruction manual and it assumes that the reader knows how to manipulate files on a Linux system.
These procedures should work on both Galileo and Galileo 2 boards.
Method 1: Dynamic linking
In the dynamic linking method the Arduino sketch is dynamically linked with the shared object library, libwolfssl.so. This method is the easiest to program for since the sketch just calls the library functions directly.
There are disadvantages to this approach, however:
- The Arduino IDE for Galileo uses a single configuration for compiling all sketches, so the linker will put a reference to libwolfssl.so in the resulting executable whether or not it’s needed by a sketch. This is not a problem if the target Galileo system has the wolfSSL library installed on it, but if any sketch is compiled for another system that does not have the library then those sketches will not execute.
- The system hosting the Arduino IDE for Galileo must have the cross-compiled wolfSSL library installed into the Arduino IDE build tree.
Method 2: Dynamic loading
In the dynamic loading method the Arduino sketch is linked with the dynamic linking loader library, libdl. The wolfSSL library and its symbols are loaded dynamically during execution using dlopen() and dlsym(). This method is more tedious to program for since the function names cannot be resolved directly by the linker and must be explicitly loaded by the code and saved as function pointers.
The advantages over the dynamic linking method are:
- libdl is part of the Galileo SD card image, so arbitrary sketches compiled by the modified IDE will still run on other Galileo systems.
- The system hosting the Arduino IDE for Galileo only needs to have the wolfSSL header files installed into the build tree.
- Any dynamic library is available to the Arduino sketch with just this single modification.
The first step in bringing SSL support to the Arduino environment is to build the wolfSSL library for Yocto using uClibc as the C library. This is accomplished using the cross compiler that is bundled with Intel’s Arduino IDE for Linux. This step must be performed on a Linux system.
There have been multiple releases of the IDE since the original Galileo release and any of them will do, but because path names have changed from release to release this document assumes that you will be using the latest build as of this writing, which is the Intel bundle version 1.0.4 with Arduino IDE version 1.6.0.
Software archive: | http://www.intel.com/content/www/us/en/do-it-yourself/downloads-and-documentation.html |
Target file: | Arduino Software 1.6.0 - Intel 1.0.4 for Linux |
Choose the 32-bit or 64-bit archive, whichever is correct for your Linux distribution.
Configuring the cross-compiler
If you have already used this version of the IDE to build sketches for your Galileo device then it has already been configured properly and you can skip this task.
If you have not built a sketch with it yet, then you will need to run the installation script in order to correctly set the path names in the package configuration files. This script, install_script.sh, is located in the hardware/tools/i586 directory inside the root of your IDE package. Run it with no arguments:
~/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.
The cross-compiler is now ready for use.
Downloading the wolfSSL source
To build the wolfSSL library for Galileo you need to download the source code from wolfSSL, Inc. As of this writing, the latest version is 3.4.0 and is distributed as a Zip archive. Unzip the source into a directory of your choosing.
Building the library
In order to build the library, you must first set up your shell environment to reference the cross compiler. The environment setup files assume a Bourne shell environment so you must perform these steps in an appropriate and compatible shell such as sh or bash. Starting from a clean shell environment is strongly recommended.
First, source the environment setup file from the Intel Arduino IDE. Be sure to use the path to your Intel Arduino IDE instead of the path given in the example:
~/src/wolfssl-3.4.0$ . ~/galileo/arduino-1.6.0+Intel/hardware/tools/i586/environment-setup-i586-poky-linux-uclibc
This step will not generate any output.
Now, you are ready to run the configure script for wolfSSL. It is necessary to provide configure with a number of options in order to properly initialize it for a cross compile.
~/src/wolfssl-3.4.0$ ./configure --prefix=$HOME/wolfssl --host=i586-poky-linux-uclibc \ --target=i586-poky-linux-uclibc
Note that you must supply absolute paths to the configure script, and cannot use ~ as a shortcut for your home directory. Use the $HOME shell variable instead.
The --prefix option tells build system where to install the library. Since you won’t actually be installing the library on this system, any directory will do. This example shows it going in $HOME/wolfssl.
The --host and --target options tell the build system that this will be a cross-compile, targeting the architecture identified as i586-poky-linux-uclibc.
The configure script will generate a lot of output. When it finishes, assuming there are no errors, you can build the software using “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'
And then install it to the local/temporary location via “make install”:
~/src/wolfssl-3.4.0$ make install
Your library will now be in the directory you specified to the --prefix option of configure, in the lib subdirectory:
~/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*
You’re now ready to install the wolfSSL library onto Galileo.
There are two general approaches for installing the wolfSSL package onto Galileo: the first is to copy the files directly to the Galileo filesystem image, and the second is to copy the files onto a running Galileo system over a network connection. In either case, however, you do need to know which image you are running on your system, the SD-Card Linux image, or the IoT Developer Kit image.
For Galileo running the SD-Card Linux image
The SD-Card Linux image is the original system image for Galileo boards. It is a very minimal system image which is less than 312 MB in size. It lacks development tools (e.g., there is no compiler) and advanced Linux utilities. As of this writing, the latest version of the SD-Card image is 1.0.4.
Software archive: | http://www.intel.com/content/www/us/en/do-it-yourself/downloads-and-documentation.html |
Target file: | SD-Card Linux Image (SDCard.1.0.4.tar.bz2) |
Both installation methods are discussed below, but installing directly to the Galileo filesystem image is preferred because you have more powerful utilities at your disposal.
Installing wolfSSL to the filesystem image
This method is easier and less error-prone than the other since you have file synchronization tools available to you, and you don’t have the added complexities of networking. All that is necessary is to mount the Galileo filesystem image as a filesystem on the build machine and then you can use rsync to copy the wolfSSL package into place. You can either copy this file to your build system, or mount the microSD card with the image directly on your Linux system using a card reader.
In the Galileo SD Card filesystem tree, the main Galileo filesystem image is called image-full-galileo-clanton.ext3 and it can be mounted using the loop device. Create a mount point (directory) on your build system—the example below uses /mnt/galileo—and then use the mount command to mount it:
~/wolfssl$ cd /mnt/mnt$ sudo mkdir galileo/mnt$ mount –t ext3 –o loop /path/to/image-full-galileo-clanton.ext3 /mnt/galileo
The Galileo filesystem should now be visible as /mnt/galileo.
Use rsync to copy the shared library and its symlinks into place. They should be installed into /usr/lib on your Galileo system:
/mnt$ rsync –a $HOME/wolfssl/lib/lib* /mnt/galileo/usr/lib
Be sure to replace $HOME/wolfSSL with the actual location of your local wolfSSL build.
Installing wolfSSL over the network
For this method, the Galileo system must be up and running with an active network connection and you will need to know its IP address. Because Galileo lacks file synchronization utilities such as rsync, files will have to be copied using tar to ensure that symbolic links are handled correctly.
First, use cd to switch to the lib subdirectory of your local wolfSSL build.
~/wolfssl$ cd $HOME/wolfssl/lib
Now use tar to create an archive of the shared library and its symlinks, and the copy it to Galileo with scp.
~/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:
Be sure to enter the IP address of your Galileo instead of the example.
Now log in to your Galileo device and untar the archive:
/tmp$ ssh root@192.168.1.2 root@192.168.1.2’s password: root@clanton:~# cd /usr/libroot@clanton:/usr/lib# tar xf /tmp/wolfssl.tar
For Galileo running the IoT Developer Kit image
The IoT Developer Kit image is a much larger and more traditional Linux system image which includes developer tools and many useful system utilities and daemons. It is distributed as a raw disk image which includes both FAT32 and ext3 disk partitions, and it must be direct-written to an SD card.
Software archive: | |
Target file: | iotdk-galileo-image.bz2 |
Both installation methods are discussed below.
As of this writing, you also need to replace the uClibc library on your Developer Kit image with the one bundled with your Intel Arduino IDE. Due to differences in the build procedure used for these two copies of the library, not all of the symbols that are exported in the IDE version are present in the Developer Kit version and that can lead to runtime crashes of Arduino sketches. The wolfSSL library, in particular, introduces a dependency on one of these symbols that is missing from the Developer Kit’s build of uClibc, and if you do not replace the library on the Galileo system attempts to use libwolfssl will fail.
Installing wolfSSL to the filesystem image
This method is easiest if you connect an SD card reader to your Linux system. Since the Developer Kit image contains an ext3 partition, most Linux distributions will automatically mount it for you, typically under /media or /mnt. Use the df command with the -T option to help you determine the mount point.
~$ df -T | grep ext3 /dev/sde2 ext3 991896 768032 172664 82% /media/johnm/048ce1b1-be13-4a5d-8352-2df03c0d9ed8
In this case, the mount point is /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/
The libraries used by Arduino sketches are kept in /lib32. Use cd to change to that directory and copy the wolfSSL shared libraries and their symlinks into this directory using rsync in order to preserve the symbolic links.
~/wolfssl$ cd /path-to-mountpoint/lib32lib32$ rsync –a $HOME/wolfssl/lib/lib* .
Be sure to replace path-to-mountpoint with the actual mount point for your SD card’s Galileo filesystem.
Now, you need to replace the Developer Kit’s uClibc library with the one from your Intel Arduino IDE package. Instead of removing it or overwriting it, the following procedure will simply rename it, effectively disabling the original copy of the library but without permanently deleting it:
lib32$ mv libuClibc-0.9.34-git.so libuClibc-0.9.34-git.so.distlib32$ cp ~/galileo/arduino-1.6.0+Intel/hardware/tools/i586/sysroots/i586-poky-linux-uclibc/lib/libuClibc-0.9.34-git.so .
Remember to use your actual path to your Intel Arduino IDE in place of the example one.
Installing wolfSSL over the network
For this method, the Galileo system must be up and running with an active network connection and you will need to know its IP address. Because Galileo lacks file synchronization utilities such as rsync, files will have to be copied using tar to ensure that symbolic links are handled correctly.
First, use cd to switch to the lib subdirectory of your local wolfSSL build.
~/wolfssl$ cd $HOME/wolfssl/lib
Now use tar to create an archive of the shared library and its symlinks, and the copy it to Galileo with scp.
~/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:
Be sure to enter the IP address of your Galileo instead of the example.
Now log in to your Galileo device and untar the archive:
/tmp$ ssh root@192.168.1.2 root@192.168.1.2’s password: root@quark:~# cd /lib32root@quark:/lib32# tar xf /tmp/wolfssl.tar
Next, you need to replace the Developer Kit’s uClibc library with the one from your Intel Arduino IDE package. Instead of removing it or overwriting it, the following procedure will simply rename it, effectively disabling the original copy of the library but without permanently deleting it (this will also prevent the actively running sketch from crashing):
root@quark:/lib32$ mv libuClibc-0.9.34-git.so libuClibc-0.9.34-git.so.dist
Log out of your Galileo system and use scp to copy the library from your Intel Arduino IDE to your 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
Remember to use your actual path to your Intel Arduino IDE in place of the example one, and your Galileo’s IP address.
To compile sketches that want to use the wolfSSL library you need to modify the compile patterns for the Arduino IDE for Galileo. The specific modification that is necessary depends on the method you have chosen for linking to libwolfssl, but no matter the method compile patters live inside of hardware/intel/i586-uclibc for the Intel 1.0.4 with Arduino IDE 1.5.3 and later.
Modifying the compile patterns
The file that holds your compile patterns is named platform.txt.
You will be editing the line “recipe.c.combine.pattern”, which looks similar to this:
## 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
Dynamic linking
If you are using the dynamic linking method, then you need to tell the linker to add libwolfssl to the list of libraries when linking the executable. Add -lwolfssl to the end of the line.
## 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
Be sure not to add any line breaks.
Dynamic loading
In the dynamic loading method, you need to tell the linker to add the dynamic loader library to the list of libraries. Add -ldl to the end of the line.
## 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
Be sure not to add any line breaks.
The last step before you can compile sketches is to install the wolfSSL build files into the Arduino IDE for Galileo build tree. For the 1.6.0 release, the build tree is in hardware/tools/i586/i586-poky-linux-uclibc. In there you will find a UNIX-like directory structure containing directories etc, lib, usr, and var.
Installing the wolfSSL header files
Whether you are using the dynamic loading or dynamic linking method you will need to have the wolfSSL header files installed where the Arduino IDE can find them so that you can include them in your sketches with:
#include <wolfssl/ssl.h>
You can find the header files in the local installation of wolfSSL that you created in Step 1, in include subdirectory. For backwards compatability reasons, the wolfSSL distribution includes header files in include/cyassl and include/wolfssl.
The wolfSSL header files must but installed into usr/include:
Installing the wolfSSL libraries
If you are using the dynamic linking method, then you must also install the cross-compiled libraries into usr/lib. You can skip this step if you are using the dynamic loading method.
The libraries are in the local installation that was created in Step 1, inside the lib directory. From there copy:
libwolfssl.la libwolfssl.so libwolfssl.so.*
All but one of the shared object files will be symlinks, but it is okay for them to be copied as just regular files.
The following example sketches show how to interact with the wolfSSL library using both the dynamic linking and dynamic loading methods. They perform the same function: connect to a target web server and fetch a web page using SSL. The page source is printed to the Arduino IDE for Galileo’s serial console.
These sketches are licensed under the Intel Sample Source Code license. In addition to browsing the source here, you can download them directly.
Dynamic linking example
/* 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 /Main_Page 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); }
Dynamic loading example
/* 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); }
INFORMATION IN THIS DOCUMENT IS PROVIDED IN CONNECTION WITH INTEL PRODUCTS. NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, TO ANY INTELLECTUAL PROPERTY RIGHTS IS GRANTED BY THIS DOCUMENT. EXCEPT AS PROVIDED IN INTEL'S TERMS AND CONDITIONS OF SALE FOR SUCH PRODUCTS, INTEL ASSUMES NO LIABILITY WHATSOEVER AND INTEL DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF INTEL PRODUCTS INCLUDING LIABILITY OR WARRANTIES RELATING TO FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR INFRINGEMENT OF ANY PATENT, COPYRIGHT OR OTHER INTELLECTUAL PROPERTY RIGHT.
UNLESS OTHERWISE AGREED IN WRITING BY INTEL, THE INTEL PRODUCTS ARE NOT DESIGNED NOR INTENDED FOR ANY APPLICATION IN WHICH THE FAILURE OF THE INTEL PRODUCT COULD CREATE A SITUATION WHERE PERSONAL INJURY OR DEATH MAY OCCUR.
Intel may make changes to specifications and product descriptions at any time, without notice. Designers must not rely on the absence or characteristics of any features or instructions marked "reserved" or "undefined." Intel reserves these for future definition and shall have no responsibility whatsoever for conflicts or incompatibilities arising from future changes to them. The information here is subject to change without notice. Do not finalize a design with this information.
The products described in this document may contain design defects or errors known as errata which may cause the product to deviate from published specifications. Current characterized errata are available on request.
Contact your local Intel sales office or your distributor to obtain the latest specifications and before placing your product order.
Copies of documents which have an order number and are referenced in this document, or other Intel literature, may be obtained by calling 1-800-548-4725, or go to: http://www.intel.com/design/literature.htm
Intel, the Intel logo, VTune, Cilk and Xeon are trademarks of Intel Corporation in the U.S. and other countries.
*Other names and brands may be claimed as the property of others
Copyright© 2012 Intel Corporation. All rights reserved.