Chapter 178. OpenSSL eCos Support
Table of Contents
178.1. Introduction
The eCosPro-SecureSockets package is a port of OpenSSL to eCos. It currently comprises a port of version 1.0.1u, but eCosCentric will issue updates from time to time after new releases become avaliable.
178.1.1. Licensing, Copyrights and Patents
OpenSSL is distributed under a BSD-style Open Source license. The
user is referred to the file LICENSE
in the
OpenSSL release for details, and is responsible for complying with
the conditions therein.
The following text on the subject of patents is adapted from text in
the README
file in the OpenSSL release:
Various companies hold various patents for various algorithms in various locations around the world. YOU are responsible for ensuring that your use of any algorithms is legal by checking if there are any patents in your country. The following are some of the patents that we know about or are rumoured to exist. This is not a definitive list.
- RSA Security holds software patents on the RC5 algorithm. If you intend to use this cipher, you must contact RSA Security for licensing conditions. Their web page is http://www.rsasecurity.com/.
- RC4 is a trademark of RSA Security, so use of this label should perhaps only be used with RSA Security's permission.
- The IDEA algorithm used to be patented by Ascom, but as of 2012, there are no longer any valid patents remaining so it may now be used patent-free.
- NTT and Mitsubishi have patents and pending patents on the Camellia algorithm, but allow use at no charge without requiring an explicit licensing agreement: http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html.
To ensure that these patents are not accidentally violated, these algorithms are disabled by default and must be enabled explicitly by the user to be included.
Part of the conditions of using OpenSSL is that the following acknowledgment be displayed and applies not only to us, here, now, but to you as well:
This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).
178.2. Configuration
OpenSSL is designed to work in large, fully featured operating systems. It expects to find a filesystem, a networking stack and a full C library. All of these things are available in eCos. However, a full configuration of this sort can be very large, both in terms of the link library generated and the size of executables. This may not be appropriate for an embedded system with limited memory availability. To mitigate these effects, the eCos port for OpenSSL has been adapted to work in three basic configurations. Users can then adapt these further to their own needs.
178.2.1. Full Configuration
Accessing the complete functionality of OpenSSL requires a fully configured
version of eCos. This should be based on the net
template together with a number of additional packages and
configurations. These additions are contained in the
openssl_full.ecm
file in the package misc
directory. This configuration may
be built using the following sequence of shell commands.
$ mkdir openssl_full $ cd openssl_full $ ecosconfig newTARGET
net $ ecosconfig import $ECOS_REPOSITORY/services/openssl/VERSION
/misc/openssl_full.ecm $ ecosconfig resolve $ ecosconfig tree $ make
The same effect can be achieved from the graphical configtool by selecting the net template and then importing the ECM file.
178.2.2. Default Configuration
If no networking is available, openssl may still be built, but only
the cryptographic and filesystem based functions may be used. This
configuration is based on the default
template
which included file I/O functions and the C library, but no
networking, plus the addition of an ECM file. This configuration
may be built with the following sequence of commands, or the
equivalent in the configtool:
$ mkdir openssl_default $ cd openssl_default $ ecosconfig newTARGET
default $ ecosconfig import $ECOS_REPOSITORY/services/openssl/VERSION
/misc/openssl_default.ecm $ ecosconfig resolve $ ecosconfig tree $ make
178.2.3. Kernel Configuration
OpenSSL will also build in a minimal kernel only configuration.
This will be based on the kernel
template plus
an ECM file. This may be built with the following commands, or the
equivalent in the configtool:
$ mkdir openssl_kernel $ cd openssl_kernel $ ecosconfig newTARGET
kernel $ ecosconfig import $ECOS_REPOSITORY/services/openssl/VERSION
/misc/openssl_kernel.ecm $ ecosconfig resolve $ ecosconfig tree $ make
This configuration is very basic, with no networking or file I/O,
only the basic cryptographic functions will be available. The ECM
file adds only STDLIB and Internationalization, mainly so that
qsort()
can be include; without this ASN1
support, and therefore most cryptographic components, cannot be
built.
178.2.4. Serial Line Support
Some parts of the OpenSSL library read data from standard input; in particular some functions read passwords with echoing disabled. They achieve this by using TERMIOS functions on the device. For this to work correctly it is necessary to configure the standard I/O to use a serial driver, and to enable TERMIOS support on it. If you intend to use serial line 0 for this, then the following ECM fragment will set up the serial device correctly:
cdl_configuration eCos { package CYGPKG_IO_SERIAL current ; }; # Enable serial device support cdl_component CYGPKG_IO_SERIAL_DEVICES { user_value 1 ; }; # Enable general TERMIOS support cdl_component CYGPKG_IO_SERIAL_TERMIOS { user_value 1; }; # Enable TERMIOS on serial 0 cdl_component CYGPKG_IO_SERIAL_TERMIOS_TERMIOS0 { user_value 1; }; # Switch standard I/O to TERMIOS device 0 cdl_option CYGDAT_LIBC_STDIO_DEFAULT_CONSOLE { user_value "\"/dev/termios0\""; };
Substitute a different serial device number for 0 in the above where necessary.
178.2.5. File System Dependencies
Much of OpenSSL can function without access to a filesystem. However, there are parts that expect to load or store data to or from files. If your application already uses a filesystem for other purposes (for example JFFS2 or YAFFS), then is should be easy to store OpenSSL's files there.
Where no external file store is available, the RAM filesystem can be used for temporary storage. The RAM filesystem can be mounted on system startup, and can be populated with files from data stored in memory. The following code shows how this might be done:
#define SERVER_CERT "/ram/server.pem" static const char server_pem[] { …. }; void init_ramfs( void ) { int fd; int err; size_t done; // Mount the RAM filesystem err = mount( "", "/ram", "ramfs" ); if( err != 0 ) diag_printf("RAMFS mount failed\n"); // Write server.pem to RAM filesystem fd = open( SERVER_CERT, O_WRONLY|O_CREAT ); done = write( fd, server_pem, sizeof(server_pem) ); if( done != sizeof(server_pem) ) diag_printf("server_pem write failed\n"); close(fd); }
Constant files can also be stored in the ROM filesystem, using mkromfs to create a file tree that can then be mounted and read.
178.2.6. Configuring OpenSSL
In addition to configuring eCos for OpenSSL, OpenSSL also contains
a number of configuration points. The OpenSSL sources have been
separated into a number of components, mainly corresponding to
specific cryptographic algorithms and other components. Each of
these is controlled by its own CDL option. By default only a subset
of components are enabled. Other components may be enabled
individually and alternatively all components may be enabled by
setting CYGPKG_OPENSSL_ALL
.
Various components of OpenSSL depend on different sets of operating system functionality, such as networking or file I/O. OpenSSL has internal configuration options to control the inclusion of different functional elements. In general we try to use those to control the build process. We have also encoded some dependencies in the CDL, both internal and external, to control the inclusion of entire components. However, the OpenSSL code is not normally compiled in systems with missing functionality, so even if the CDL and OpenSSL dependencies are correct, it is still possible for builds to fail with compile or link errors.
178.3. openssl Command Tool
The OpenSSL package contains a command line tool, openssl, that can be used to test the openssl package and to generate keys and certificates. This command can either execute a single command at a time, or run in interactive mode where successive commands are issued to a prompt. Under eCos it only runs in interactive mode, taking commands and issuing responses to the serial console.
The openssl tool will only build and run in the full configuration and additionally needs the RAM filesystem. If passwords are to be supplied, the serial line support described earlier should be enabled.
The command executable is created and saved in the INSTALL_DIR/bin
directory. Both the
original ELF file and an SREC file,
openssl.srec
are saved here. To run the command
transfer the SREC file to your TFTP server and download and run it
under RedBoot. You should see something similar to the following:
RedBoot> load openssl.srec Using default protocol (TFTP) Entry point: 0x20040040, address range: 0x20040000-0x201e76ec RedBoot> go [cyg_net_init] Init: mbinit(0x00000000) [cyg_net_init] Init: cyg_net_init_devs(0x00000000) Init device 'dm9000_eth0' [cyg_net_init] Init: loopattach(0x00000000) [cyg_net_init] Init: ifinit(0x00000000) [cyg_net_init] Init: domaininit(0x00000000) [cyg_net_init] Init: cyg_net_add_domain(0x201e51b0) New domain internet at 0x00000000 [cyg_net_init] Init: cyg_net_add_domain(0x201e2c4c) New domain route at 0x00000000 [cyg_net_init] Init: call_route_init(0x00000000) [cyg_net_init] Done mount /ram set current directory to /ram load openssl.cnf into /ram/openssl.cnf initialise network interfaces BOOTP[eth0] op: REPLY htype: Ethernet hlen: 6 hops: 0 xid: 0x0 secs: 0 flags: 0x0 hw_addr: 00:03:47:df:32:a8 client IP: 192.168.7.20 my IP: 192.168.7.20 server IP: 192.168.7.22 gateway IP: 192.168.0.1 options: subnet mask: 255.255.0.0 IP broadcast: 192.168.255.255 gateway: 192.168.0.1 [eth_drv_ioctl] Warning: Driver can't set multi-cast mode [eth_drv_ioctl] Warning: Driver can't set multi-cast mode [eth_drv_ioctl] Warning: Driver can't set multi-cast mode Start OpenSSL OpenSSL> version OpenSSL 1.0.0c 2 Dec 2010 OpenSSL>
The RAM filesystem is mounted and /ram
is set as the current
directory. It is therefore possible to test the generation of keys
and certificates into files:
OpenSSL> req -x509 -nodes -days 36500 \ -subj "/C=GB/ST=England/L=Cambridge/O=eCosCentric/CN=ecoscentric.com" \ -newkey rsa:1024 -keyout mycert.pem -out mycert.pem Generating a 1024 bit RSA private key …………........++++++ ……..++++++ writing new private key to 'mycert.pem' ----- OpenSSL>
If you want to enter passwords without reflection, you need to enable the TERMIOS support described above.
The eCos hosted openssl command serves as a test for OpenSSL functionality, and is a good check that the library is complete. However, it is of little practical use and has some limitations. While is possible to generate key files and certificates, it is not then easy to get then off the board for future use, unless they are stored to an external medium such as an SD card. It is recommended, instead, that a host based version of openssl be used to do this. Files may then be imported via removable media, or written to the RAM filesystem as described above. Another limitation is that if you run the s_server command, you cannot terminate it. Under Unix/Linux this command relies on catching the signal generated by a Ctrl-C to terminate; there is no support for this under eCos and the only way to terminate this command is to reboot and reload openssl.
178.4. Thread Safety
The OpenSSL library does not directly contain support for thread safe code. Instead it relies on application code to register some callbacks to perform the locking required. Under eCos there are two ways of doing this: through the POSIX compatibility package and directly using eCos APIs.
POSIX locking support is already available in OpenSSL. Example code
is available in src/crypto/threads/th-lock.c
,
and similar code is tested in the mttest
test
program. However, this code will only work in threads that have been
created using pthread_create()
, or in the
main()
application thread.
eCos locking support uses lower level primitives and can be used from any kind of thread. In order to provide locking, an application must register two callbacks with the library, and set up an array of locks that the library will request it to lock and unlock. The following code does this:
// Forward definitions for callback functions. void ecos_locking_callback(int mode, int type, char *file, int line); unsigned long ecos_thread_id_callback(void); // Pointer to array of locks. static cyg_mutex_t *lock_cs; // This function allocates and initializes the lock array // and registers the callbacks. This should be called // after the OpenSSL library has been initialized and // before any new threads are created. void thread_setup(void) { int i; // Allocate lock array according to OpenSSL's requirements lock_cs=OPENSSL_malloc(CRYPTO_num_locks() * sizeof(cyg_mutex_t)); // Initialize the locks for (i=0; i<CRYPTO_num_locks(); i++) { cyg_mutex_init(&(lock_cs[i])); } // Register callbacks CRYPTO_set_id_callback((unsigned long (*)())ecos_thread_id_callback); CRYPTO_set_locking_callback((void (*)())ecos_locking_callback); } // This function deallocates the lock array and deregisters the // callbacks. It should be called after all threads have // terminated. void thread_cleanup(void) { int i; // Deregister locking callback. No real need to // deregister id callback. CRYPTO_set_locking_callback(NULL); // Destroy the locks for (i=0; i<CRYPTO_num_locks(); i++) { cyg_mutex_destroy(&(lock_cs[i])); } // Release the lock array. OPENSSL_free(lock_cs); } // Locking callback. The type, file and line arguments are // ignored. The file and line may be used to identify the site of the // call in the OpenSSL library for diagnostic purposes if required. void ecos_locking_callback(int mode, int type, char *file, int line) { if (mode & CRYPTO_LOCK) { cyg_mutex_lock(&(lock_cs[type])); } else { cyg_mutex_unlock(&(lock_cs[type])); } } // Thread id callback. unsigned long ecos_thread_id_callback(void) { return (unsigned long)cyg_thread_get_id(cyg_thread_self()); }
Example code similar to this can be found in the
mttest_ecos
test program.
178.5. eCos Customization
The eCos port of OpenSSL contains a number of customizations to adapt OpenSSL to the eCos environment.
178.5.1. Random Number Support
To function correctly, OpenSSL requires a source of cryptographically strong random numbers. These are usually sourced either from operating system level entropy gathering or from a hardware random number generator. At present eCos does not have any entropy gathering mechanism so the only viable source is a hardware RNG. Without entropy gathering or hardware RNG use, some forms of encrypted data may be more vulnerable to attack. Contact eCosCentric if a solution is required for this.
OpenSSL gathers random numbers by calling
RAND_poll()
when necessary. This function is
responsible for
calling RAND_add()
to mix new random data into OpenSSL's PRNG state. Application code can also
call RAND_add()
directly to add entropy from any
source.
The source file src/ecos/rand_ecos.c
contains
an implementation of RAND_poll()
that adds
data from a static table whenever called. This is clearly not
cryptographically strong, since the same random data will be added
each time an application starts. This implementation is adequate
for testing the library only and should not be used for real
applications. The eCos port of OpenSSL does not automatically
use a hardware RNG if present, and so application code is
responsible for calling RAND_add()
to incorporate random entropy from a hardware RNG into OpenSSL's PRNG.
178.5.2. BIO_diag
OpenSSL implements a general purpose data source/sink/filter object
called a BIO
. These may be attached to various
sources and sinks such as C library FILEs, file descriptors and
sockets. Many functions that need to output messages take a pointer
to a BIO
as an argument, which is typically
attached to stdout
or stderr
.
In certain eCos configurations these streams are not present, but
we still want to use these functions and supply a
BIO
for output.
eCos implements a new BIO
type,
BIO_diag
which outputs any data on the eCos
diagnostic channel. It can be created using the new function
BIO *BIO_new_diag(void)
, and can subsequently
be used in place of any other output-only
BIO
. It may be freed in the usual way with
BIO_free()
.
178.6. Tests
OpenSSL contains a number of test programs that validate the correctness of various cryptographic algorithms and test the functioning of the OpenSSL library. Most of these tests have been ported directly to eCos with only minor changes to allow them to function in the eCos test environment. Since all these tests expect to use C library standard I/O (STDIO) for output, they will only be built if that package is configured in.
A small number of encryption algorithm tests have been further
adapted to function without needing STDIO. This has mainly involved
replacing (f)printf
with
diag_printf
, but also includes spawning a
thread to run the test with sufficient stack. These tests are all
named the same as the base OpenSSL test from which they were
derived with the addition of _ecos
to the file
name.
The test program ssltest1
is the only purpose
written SSL test program. It is a simple client that attempts to
contact an SSL server and send it some data. The server it contacts
is defined by the configuration options
CYGDAT_OPENSSL_TESTS_SERVER_IP
and
CYGDAT_OPENSSL_TESTS_SERVER_PORT
which are used to set
IP address and port number of the server to contact. A suitable
server can be run using the s_server command of
the openssl tool on the host with the configured
IP address. The shell script in misc/runtest
within the eCos OpenSSL package in the package repository
should do this correctly for any Linux host.
The test program openssl1
is a version of the
openssl command line tool that runs a sequence of
predefined commands to test the library as a whole. One of the
commands that this test runs is a timing test against the same
server that ssltest1
uses.
178.7. Limitations
OpenSSL includes files crypto/asn1/a_utctm.c
and src/crypto/asn1/a_time.c
which have hard-coded
year limits of 2050. Use beyond that year is at present unsupported,
although it is expected that upstream OpenSSL will resolve this at some
point.
2024-03-18 | eCosPro License |