Bringing SSL to Arduino on the Intel Galileo board through wolfSSL

Published Date
13 - May - 2015
| Last Updated
27 - May - 2015
 
Bringing SSL to Arduino on the Intel Galileo board through wolfSS...

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.

Getting Started

This paper looks at two methods for linking the wolfSSL library to an Arduino sketch, but both of them follow the same basic steps:
1. Build wolfSSL for Yocto
2. Install the wolfSSL shared library onto your Galileo image
3. Modify the compile patterns for the Arduino IDE for Galileo
4. 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.

 

Step 1: Building wolfSSL for Yocto

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.
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.
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.

Step 2: Installing wolfSSL On 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.
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 file system 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/lib
root@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.

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/lib32
lib32$ 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.dist
lib32$ 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.
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 /lib32
root@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.

Step 3: Modifying the Compile Patterns for the Arduino IDE

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.

Step 4: Installing the wolfSSL Build Files on the Arduino IDE System

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.

Example Sketches

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.

Note: Be sure to change the server name and, if necessary, the page URL to fetch.
Dynamic linking example

001 /*

002 Copyright 2015 Intel Corporation All Rights Reserved.

003
 

004 The source code, information and material ("Material") contained herein is owned

005 by Intel Corporation or its suppliers or licensors, and title to such Material

006 remains with Intel Corporation or its suppliers or licensors. The Material

007 contains proprietary information of Intel or its suppliers and licensors. The

008 Material is protected by worldwide copyright laws and treaty provisions. No part

009 of the Material may be used, copied, reproduced, modified, published, uploaded,

010 posted, transmitted, distributed or disclosed in any way without Intel's prior

011 express written permission. No license under any patent, copyright or other

012 intellectual property rights in the Material is granted to or conferred upon

013 you, either expressly, by implication, inducement, estoppel or otherwise. Any

014 license under such intellectual property rights must be express and approved by

015 Intel in writing.

016
 

017 Include any supplier copyright notices as supplier requires Intel to use.

018
 

019 Include supplier trademarks or logos as supplier requires Intel to use,

020 preceded by an asterisk. An asterisked footnote can be added as follows: *Third

021 Party trademarks are the property of their respective owners.

022
 

023 Unless otherwise agreed by Intel in writing, you may not remove or alter this

024 notice or any other notice embedded in Materials by Intel or Intel's suppliers

025 or licensors in any way.

026 */

027
 

028 #include <LiquidCrystal.h>

029 #include <dlfcn.h>

030 #include <wolfssl/ssl.h>

031 #include <Ethernet.h>

032 #include <string.h>

033
 

034 const char server[]= "www.example.com"; // Set this to a web server of your choice

035 const char req[]= "GET / HTTP/1.0\r\n\r\n"; // Get the root page

036
 

037 int repeat;

038
 

039 int wolfssl_init ();

040 int client_send (WOLFSSL *, char *, int, void *);

041 int client_recv (WOLFSSL *, char *, int, void *);

042
 

043 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

044 void *handle;

045
 

046 EthernetClient client;

047
 

048
 

049 WOLFSSL_CTX *ctx= NULL;

050 WOLFSSL *ssl= NULL;

051 WOLFSSL_METHOD *method= NULL;

052
 

053 void setup() {

054  Serial.begin(9600);

055 Serial.println("Initializing");

056
     

057 lcd.begin(16,2);

058  lcd.clear();

059
 

060  if ( wolfssl_init() == 0 ) goto fail;

061
     

062 Serial.println("OK");

063
     

064 // Set the repeat count to a maximum of 5 times so that we aren't

065 // fetching the same URL over and over forever.

066
     

067 repeat= 5;

068  return;

069
 

070 fail:

071 Serial.print("wolfSSL setup failed");

072 repeat= 0; 

073 }

074
 

075 int wolfssl_init ()

076 {

077 char err[17];

078
     

079 // Create our SSL context

080
     

081 method= wolfTLSv1_2_client_method();

082 ctx= wolfSSL_CTX_new(method);

083 if ( ctx == NULL ) return 0;

084
     

085  // Don't do certification verification

086 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);

087
     

088  // Specify callbacks for reading to/writing from the socket (EthernetClient

089 // object).

090
     

091 wolfSSL_SetIORecv(ctx, client_recv);

092 wolfSSL_SetIOSend(ctx, client_send);

093
     

094 return 1;

095 }

096
 

097 int client_recv (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)

098 {

099 int i= 0;

100
     

101  // Read a byte while one is available, and while our buffer isn't full.

102
     

103 while ( client.available() > 0 && i < sz) {

104 buf[i++]= client.read();

105 }

106
 

107  return i;

108 }

109
 

110 int client_send (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)

111 {

112 int n= client.write((byte *) buf, sz);

113  return n;

114 }

115
 

116 void loop() {

117 char errstr[81];

118 char buf[256];

119 int err;

120
     

121 // Repeat until the repeat count is 0.

122
     

123 if (repeat) {

124  if ( client.connect(server, 443) ) {

125 int bwritten, bread, totread;

126
             

127 Serial.print("Connected to ");

128 Serial.println(server);

129
 

130  ssl= wolfSSL_new(ctx);

131  if ( ssl == NULL ) {

132  err= wolfSSL_get_error(ssl, 0);

133
                wolfSSL_ERR_error_string_n(err, errstr, 80);

134
                Serial.print("wolfSSL_new: ");

135
                Serial.println(errstr);

136
            }

137
 

138
            Serial.println(req);

139
            bwritten= wolfSSL_write(ssl, (char *) req, strlen(req));

140
            Serial.print("Bytes written= ");

141
            Serial.println(bwritten);

142
             

143
            if ( bwritten > 0 ) {

144
                totread= 0;

145
                 

146
                while ( client.available() || wolfSSL_pending(ssl) ) {

147
                    bread= wolfSSL_read(ssl, buf, sizeof(buf)-1);

148
                    totread+= bread;

149
                     

150
                    if ( bread > 0 ) {                  

151
                        buf[bread]= '\0';

152
                        Serial.print(buf);

153
                    } else {

154
                        Serial.println();

155
                        Serial.println("Read error");

156
                    }

157
                }

158
                 

159
                Serial.print("Bytes read= ");

160
                Serial.println(bread);

161
            }

162
             

163
            if ( ssl != NULL ) wolfSSL_free(ssl);

164
 

165
            client.stop();

166
            Serial.println("Connection closed");

167
        }

168
         

169
        --repeat;

170
    }

171
     

172
    // Be polite by sleeping between iterations

173
     

174
    delay(5000);

175
}

Dynamic loading example
view sourceprint?

001 /*

002 Copyright 2015 Intel Corporation All Rights Reserved.

003
 

004 The source code, information and material ("Material") contained herein is owned

005 by Intel Corporation or its suppliers or licensors, and title to such Material

006 remains with Intel Corporation or its suppliers or licensors. The Material

007 contains proprietary information of Intel or its suppliers and licensors. The

008 Material is protected by worldwide copyright laws and treaty provisions. No part

009 of the Material may be used, copied, reproduced, modified, published, uploaded,

010 posted, transmitted, distributed or disclosed in any way without Intel's prior

011 express written permission. No license under any patent, copyright or other

012 intellectual property rights in the Material is granted to or conferred upon

013 you, either expressly, by implication, inducement, estoppel or otherwise. Any

014 license under such intellectual property rights must be express and approved by

015 Intel in writing.

016
 

017 Include any supplier copyright notices as supplier requires Intel to use.

018
 

019 Include supplier trademarks or logos as supplier requires Intel to use,

020 preceded by an asterisk. An asterisked footnote can be added as follows: *Third

021 Party trademarks are the property of their respective owners.

022
 

023 Unless otherwise agreed by Intel in writing, you may not remove or alter this

024 notice or any other notice embedded in Materials by Intel or Intel's suppliers

025 or licensors in any way.

026 */

027
 

028 #include <dlfcn.h>

029 #include <wolfssl/ssl.h>

030 #include <Ethernet.h>

031 #include <string.h>

032
 

033 /*

034 Set this to the location of your wolfssl shared library. By default you 

035 shouldn't need to specify a path unless you put it somewhere other than

036
/usr/lib (SD-Card image) or /lib32 (IoT Developer Kit image).

037
*/

038 #define WOLFSSL_SHLIB_PATH "libwolfssl.so"

039
 

040 const char server[]= "www.example.com"; // Set this to a web server of your choice

041 const char req[]= "GET / HTTP/1.0\r\n\r\n"; // Get the root page

042 int repeat;

043
 

044 int wolfssl_dlload ();

045 int wolfssl_init ();

046 int client_send (WOLFSSL *, char *, int, void *);

047 int client_recv (WOLFSSL *, char *, int, void *);

048
 

049 void *handle;

050
 

051 EthernetClient client;

052
 

053
 

054 WOLFSSL_CTX *ctx= NULL;

055 WOLFSSL *ssl= NULL;

056 WOLFSSL_METHOD *method= NULL;

057
 

058 typedef struct wolfssl_handle_struct {

059  WOLFSSL_METHOD *(*wolfTLSv1_2_client_method)();

060
    WOLFSSL_CTX *(*wolfSSL_CTX_new)(WOLFSSL_METHOD *);

061 void (*wolfSSL_CTX_set_verify)(WOLFSSL_CTX *, int , VerifyCallback);
   

062 int (*wolfSSL_connect)(WOLFSSL *);
   

063
    int (*wolfSSL_shutdown)(WOLFSSL *);

064int (*wolfSSL_get_error)(WOLFSSL *, int);
    

065  void (*wolfSSL_ERR_error_string_n)(unsigned long, char *, unsigned long);
  

066  WOLFSSL *(*wolfSSL_new)(WOLFSSL_CTX *);
  

067   void (*wolfSSL_free)(WOLFSSL *);
 

068  void (*wolfSSL_SetIORecv)(WOLFSSL_CTX *, CallbackIORecv);
  

069  void (*wolfSSL_SetIOSend)(WOLFSSL_CTX *, CallbackIORecv);
  

070  int (*wolfSSL_read)(WOLFSSL *, void *, int);
  

071  int (*wolfSSL_write)(WOLFSSL *, void *, int);
  

072   int (*wolfSSL_pending)(WOLFSSL *);
 

073 } wolfssl_t;

074
 

075 wolfssl_t wolf;

076
 

077 void setup() {

078
    Serial.begin(9600);

079  Serial.println("Initializing");
  

080
 

081   if ( wolfssl_dlload() == 0 ) goto fail;
 

082   if ( wolfssl_init() == 0 ) goto fail;
 

083
     

084  // Set the repeat count to a maximum of 5 times so that we aren't
  

085  // fetching the same URL over and over forever.
  

086
     

087   repeat= 5;
 

088  return;
  

089
 

090 fail:

091  Serial.print("wolfSSL setup failed");
  

092   repeat= 0; 
 

093 }

094
 

095 int wolfssl_init ()

096 {

097    char err[17];
 

098
     

099   // Create our SSL context
 

100
     

101   method= wolf.wolfTLSv1_2_client_method();
 

102  ctx= wolf.wolfSSL_CTX_new(method);
  

103   if ( ctx == NULL ) return 0;
 

104
     

105  // Don't do certification verification
  

106   wolf.wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
 

107
     

108    // Specify callbacks for reading to/writing from the socket (EthernetClient

109   // object).
 

110
     

111  wolf.wolfSSL_SetIORecv(ctx, client_recv);
  

112 wolf.wolfSSL_SetIOSend(ctx, client_send);
   

113
     

114   return 1;
 

115 }

116
 

117
 

118 {

119 // Dynamically load our symbols from libwolfssl.so
    

120
     

121  char *err;
  

122
     

123   // goto is useful for constructs like this, where we need everything to succeed or
 

124  // it's an overall failure and we abort. If just one of these fails, print an error
  

125    // message and return 0.

126
     

127 handle= dlopen(WOLFSSL_SHLIB_PATH, RTLD_NOW);
   

128  if ( handle == NULL ) {
  

129   err= dlerror();
     

130  goto fail;
      

131  }

132
 

133  wolf.wolfTLSv1_2_client_method= (WOLFSSL_METHOD *(*)()) dlsym(handle, "wolfTLSv1_2_client_method");
  

134    if ( (err= dlerror()) != NULL ) goto fail;

135
     

136   wolf.wolfSSL_CTX_new= (WOLFSSL_CTX *(*)(WOLFSSL_METHOD *)) dlsym(handle, "wolfSSL_CTX_new");
 

137   if ( (err= dlerror()) != NULL ) goto fail;
 

138
     

139 wolf.wolfSSL_CTX_set_verify= (void (*)(WOLFSSL_CTX* , int , VerifyCallback)) dlsym(handle, "wolfSSL_CTX_set_verify");
   

140   if ( (err= dlerror()) != NULL ) goto fail;
 

141
     

142   wolf.wolfSSL_connect= (int (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_connect");
 

143    if ( (err= dlerror()) != NULL ) goto fail;

144
     

145  wolf.wolfSSL_get_error= (int (*)(WOLFSSL *, int)) dlsym(handle, "wolfSSL_get_error");
  

146  if ( (err= dlerror()) != NULL ) goto fail;
  

147
     

148 wolf.wolfSSL_ERR_error_string_n= (void (*)(unsigned long, char *, unsigned long)) dlsym(handle, "wolfSSL_ERR_error_string_n");
    

149   if ( (err= dlerror()) != NULL ) goto fail;
 

150
     

151  wolf.wolfSSL_new= (WOLFSSL *(*)(WOLFSSL_CTX *)) dlsym(handle, "wolfSSL_new");
  

152    if ( (err= dlerror()) != NULL ) goto fail;

153
     

154  wolf.wolfSSL_free= (void (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_free");
  

155   if ( (err= dlerror()) != NULL ) goto fail;
 

156
 

157  wolf.wolfSSL_SetIORecv= (void (*)(WOLFSSL_CTX *, CallbackIORecv)) dlsym(handle, "wolfSSL_SetIORecv");
  

158   if ( (err= dlerror()) != NULL ) goto fail; 
 

159
 

160   wolf.wolfSSL_SetIOSend= (void (*)(WOLFSSL_CTX *, CallbackIORecv)) dlsym(handle, "wolfSSL_SetIOSend");
 

161   if ( (err= dlerror()) != NULL ) goto fail;
 

162
 

163   wolf.wolfSSL_read= (int (*)(WOLFSSL *, void *, int)) dlsym(handle, "wolfSSL_read");
 

164    if ( (err= dlerror()) != NULL ) goto fail;

165
         

166    wolf.wolfSSL_write= (int (*)(WOLFSSL *, void *, int)) dlsym(handle, "wolfSSL_write");

167   if ( (err= dlerror()) != NULL ) goto fail;
 

168
     

169    wolf.wolfSSL_pending= (int (*)(WOLFSSL *)) dlsym(handle, "wolfSSL_pending");
 

170  if ( (err= dlerror()) != NULL ) goto fail;
  

171
     

172    Serial.println("OK");

173
     

174
    return 1;

175
 

176 fail:

177    Serial.println(err);

178  return 0;
  

179}

180
 

181 int client_recv (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)

182{

183   int i= 0;
 

184
     

185  // Read a byte while one is available, and while our buffer isn't full.
  

186
     

187  while ( client.available() > 0 && i < sz) {
  

188    buf[i++]= client.read();
    

189    }

190
 

191  return i;
  

192}

193
 

194 int client_send (WOLFSSL *_ssl, char *buf, int sz, void *_ctx)

195 {

196  int n= client.write((byte *) buf, sz);
  

197  return n;
  

198 }

199
 

200 void loop() {

201 char errstr[81];
   

202  char buf[256];
  

203 int err;
   

204
     

205  // Repeat until the repeat count is 0.
  

206
     

207  if (repeat) {
  

208  if ( client.connect(server, 443) ) {
       

209  int bwritten, bread, totread;
           

210
             

211 Serial.print("Connected to ");
            

212  Serial.println(server);
           

213
 

214  ssl= wolf.wolfSSL_new(ctx);
           

215  if ( ssl == NULL ) {
           

216 err= wolf.wolfSSL_get_error(ssl, 0);
                

217 wolf.wolfSSL_ERR_error_string_n(err, errstr, 80);
                

218 Serial.print("wolfSSL_new: ");
                

219 Serial.println(errstr);
                

220 }

221
 

222 Serial.println(req);
            

223 bwritten= wolf.wolfSSL_write(ssl, (char *) req, strlen(req));
           

224  Serial.print("Bytes written= ");
           

225 Serial.println(bwritten);
            

226
             

227   if ( bwritten > 0 ) {
          

228  totread= 0;
               

229
                 

230 while ( client.available() || wolf.wolfSSL_pending(ssl) ) {
                

231bread= wolf.wolfSSL_read(ssl, buf, sizeof(buf)-1);
                    

232   totread+= bread;
                  

233
                     

234  if ( bread > 0 ) {
                   

235  buf[bread]= '\0';
                       

236  Serial.print(buf);
                       

237 } else {
                    

238 Serial.println();
                        

239  Serial.println("Read error");
                       

240 }
                    

241  }

242
                 

243
                Serial.print("Bytes read= ");

244  Serial.println(totread);

245 }

246
             

247if ( ssl != NULL ) wolf.wolfSSL_free(ssl);

248
 

249 client.stop();

250  Serial.println("Connection closed");

251 }

252
         

253  --repeat;

254  }

255
     

256 // Be polite by sleeping between iterations

257
     

258  delay(5000);

259 }

Notices

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 FREE, or go to:  http://www.intel.com/design/literature.html
Intel, the Intel logo, VTune, Cilk and Xeon are trademarks of Intel Corporation in the U.S. and other countries.