Yocto Openssh



IMAGEINSTALL += 'openssh openssl openssh-sftp-server' These two directives are key ingredients in any bitbake recipe. Here is a description of what each does: require: this directive tells bitbake that you want to parse the core-image-minimal.bb recipe file and insert the file in that location. Essentially what this line is telling bitbake to. Per the Yocto Mega Manual, section 5.2.2, the correct image should be 'core-image-full-cmdline', since: - Galileo does not have video output, and is therefore a Command Line Interface (CLI) bound device via serial/sshd/telnet.

  1. Yocto Openssh Permitrootlogin
  2. Yocto Openssh Instead Of Dropbear

Looking for the best way to explore embedded Linux, I found Open Embedded. OE is a nice middle-ground between the options on each extreme. On one hand, you can run a full distribution like Ubuntu on ARM. On the other, you can pull together the kernel and BSP and software you need, plus a toolchain for your kit, and compile straight away. OE gives you the control of compiling everything yourself–I had a fully functioning machine on the network, with an SSH server, using 10MB storage without too much tweaking. Plus it gives you the power of a distribution by collecting piles of software to choose from.

The trick to OE is that it ships as a collection of instructions, called ‘recipes’, which fetch each package from the right place, apply the necessary patches, build it, package it, and prepare an image. It builds its own toolchain, which takes away one of the big headaches of embedded development, and packages up an entire cross SDK we can use to build further applications and deploy them onto target hardware.

In this blog post, I’ll bring up a minimal system under emulation, to get a feel for the system without having to commit to hardware.

  • $ cd /path/to/docker-yocto-imx # build image $ docker build -t yocto-imx. # Run a new container $ docker run -p 2222:22 -it -name yocto yocto-imx bash # Then you can run a new process like this: $ docker exec-it yocto bash # You can also manage this container to start / stop / restart $ docker start yocto.
  • WolfSSL maintains a Yocto and OpenEmbedded (OE) layer including recipes for wolfSSL products (wolfSSL, wolfSSH, wolfMQTT, wolfTPM), examples, and support for building other Open Source recipes with wolfSSL support. This layer is named “ meta-wolfssl ”, and is available on GitHub.

Getting Yocto/Poky

Early on, I was advised by the oe-core mailing list, to start with The Yocto Project. From what I can tell, Yocto provides a stabilization point in the vast, fast-moving soup of OE recipes, plus documentation and testing. That is, it gives us a stable starting point.

Let’s start with the Denzil release of the tools, available from the Yocto Download page.

One thing to note in the Yocto world is that the thing you download is actually called ‘Poky’. The exact difference between Poky and Yocto is not established in a clear way that understandable to outsiders. The nearest way I’ve found to approximate the terms is to use ‘Yocto’ when referring to the organization (like one would refer to ‘Canonical’), use ‘Poky’ when referring to the actual bits downloaded (analagous to ‘Ubuntu’), and ‘Denzil’ is the release (like ‘oneric’).

Here’s how we download the files and get them ready. This is running on Ubuntu 12.04, and of course you could put these files anywhere convenient:

$ cd ~/Source/Yocto
$ wget http://downloads.yoctoproject.org/releases/yocto/yocto-1.2/poky-denzil-7.0.tar.bz2 -O - | tar xjv
$ source poky-denzil-7.0/oe-init-build-env poky-denzil-7.0-build

Poky will live in two directories. The first, poky-denzil-7.0, contains the files we downloaded. The second, poky-denzil-7.0-build, contains files generated BY the build system itself.

The last line above is critical. It sets up the environment for any future commands.

From here on, it’s helpful to following along with The Yocto Project Quick Start.

Configure

Within the build directory, under ‘conf’, is a critical file, ‘local.conf’. It stores configuration settings that affect the entire build. The basic thing to change here is the machine we’re building for, in this case ‘qemuarm’. While we’re at it, we can increase the number of threads and parallel make options, to build faster.

MACHINE = 'qemuarm'
BB_NUMBER_THREADS = '2'
PARALLEL_MAKE = '-j 6'

Fetch & Build

There are numerous different images we can build. Here, we’ll start with a simple one, ‘core-image-minimal’. This is just enough to get a useful command line up.

I prefer to fetch and build in two different steps to keep tabs on the performance of my machine. I did in-fact purpose-build my machine for fast compile times 🙂 First, the ‘fetchall’ command will download all the needed files to the local machine:

Second, let’s build it!

$ time bitbake core-image-minimal
real 34m26.539s
user 86m48.430s
sys 12m14.182s

Obviously, the time this takes varies wildly. On my previous machine, it took over 3 hours.

Run It!

Now we can run our vanilla image. This tells us all is well with our download, and from here we can start customizing our image.

To log in, use user ‘root’, which requires no password.

Next Steps

That’s all it takes to get the basic system up. Not bad! My hats off to the Yocto guys getting a stable, reliable, and powerful build put together.

Beyond just getting started, there are a handful of really useful things we can also do:

  • Set Up SSH. We’ll want to access our ‘machine’ remotely to move files over, and prepare for the day when we’re running real hardware which is not connected directly to our development machine.
  • Cross-Develop Applications. A linux machine by itself isn’t that useful until we’ve got it doing what we want. Chances are, this requires building apps on our development machine and running them on the target hardware.
  • Optimization. Poky builds things out of the box that we don’t necessarily need, so it’s good to know how to reduce the footprint further so as to reduce the cost of the final product.

Set Up SSH

Adding a SSH server to our image is pretty simple, and highlights the general ease with which existing packages can be added into the minimal installation. The basic idea is to edit our image reciple, meta/recipes-core/images/core-image-minimal.bb, and edit the IMAGE_INSTALL line to add task-core-openssh. Now it looks like this:

IMAGE_INSTALL = 'task-core-boot task-core-ssh-openssh ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}'

There are two problems with this, however. For one, how do we get the public keys onto the machine? We could log into the machine and wget them over from a known server, but that’s a pain to do every time we launch a new image. For another, the ssh server regenerates server keys each time, which gets highly annoying when they keys change from build to build.

The solution is to add a user’s public keys to the image, and to generate server keys and add those into the image as well. This will be an excellent way to learn how to modify an OE recipe! The file we need is the openssh recipe, meta/recipes-connectivity/openssh/openssh_5.9p1.bb.

First, we increase the revision number of the recipe, because we’re changing the contents

@@ -7,7 +7,7 @@ SECTION = 'console/network'
LICENSE = 'BSD'
LIC_FILES_CHKSUM = 'file://LICENCE;md5=bae9a689be41581503bcf95d8fb42c4e'
-PR = 'r3'
+PR = 'r4'

Tell the recipe where to find the server keys:

@@ -22,6 +22,7 @@ SRC_URI = 'ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar.
file://nostrip.patch
file://sshd_config
file://ssh_config
+ file://sshd-keys.tar

Tell the recipe to install the server keys into the final image:

@@ -81,6 +82,12 @@ do_install_append () {
mv ${D}${bindir}/ssh ${D}${bindir}/ssh.${PN}
rm -f ${D}${bindir}/slogin ${D}${datadir}/Ssh.bin
rmdir ${D}/var/run/sshd ${D}/var/run ${D}/var
+ install -m 0600 ${WORKDIR}/ssh_host_dsa_key ${D}${sysconfdir}/ssh
+ install -m 0600 ${WORKDIR}/ssh_host_rsa_key ${D}${sysconfdir}/ssh
+ install -m 0600 ${WORKDIR}/ssh_host_ecdsa_key ${D}${sysconfdir}/ssh
+ install -m 0644 ${WORKDIR}/ssh_host_dsa_key.pub ${D}${sysconfdir}/ssh
+ install -m 0644 ${WORKDIR}/ssh_host_rsa_key.pub ${D}${sysconfdir}/ssh
+ install -m 0644 ${WORKDIR}/ssh_host_ecdsa_key.pub ${D}${sysconfdir}/ssh

That’s all the changes needed to the openssh recipe. Now, we need to get those sshd-keys in the right place:

$ cd ~/Source/Yocto/poky-denzil-7.0/meta/recipes-connectivity/openssh/openssh-5.9p1/
$ ssh-keygen -q -f ssh_host_rsa_key -N ' -t rsa
$ ssh-keygen -q -f ssh_host_ecdsa_key -N ' -t ecdsa
$ ssh-keygen -q -f ssh_host_dsa_key -N ' -t dsa
$ tar cf sshd-keys.tar ssh_host*
$ rm ssh_host*

That’s it for the server keys. Now, let’s get a user public key onto the image. While we’re at it, we can modify sshd_config to have some friendlier settings. We can add base file to the system by modifying the meta/recipes-core/base-files/base-files_3.0.14.bb recipe.

Again, increase the revision number:

@@ -1,7 +1,7 @@
SUMMARY = 'Miscellaneous files for the base system.'
DESCRIPTION = 'The base-files package creates the basic system directory structure and provides a small set of key configuration files for the system.'
SECTION = 'base'
-PR = 'r71'
+PR = 'r72'

Let the recipe know about the additional file. Be sure to actually put this file in meta/recipes-core/base-files/base-files.

@@ -22,6 +22,7 @@ SRC_URI = 'file://rotation
file://issue.net
file://issue
file://usbd
+ file://authorized_keys2

Tell the recipe to install it into the final image:

@@ -91,6 +92,7 @@ do_install () {
install -m 0644 ${WORKDIR}/rotation ${D}${sysconfdir}/rotation
fi
+ install -m 0644 ${WORKDIR}/authorized_keys2 ${D}${sysconfdir}/authorized_keys2

Finally, we can make these changes to the existing meta/recipes-connectivity/openssh/openssh-5.9p1/sshd_config file:

@@ -45,7 +45,7 @@ Protocol 2
#RSAAuthentication yes
#PubkeyAuthentication yes
-#AuthorizedKeysFile .ssh/authorized_keys
+AuthorizedKeysFile /etc/authorized_keys2
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
@@ -58,7 +58,7 @@ Protocol 2
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
-#PasswordAuthentication yes
+PasswordAuthentication no
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
@@ -95,7 +95,7 @@ Protocol 2
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
-UsePrivilegeSeparation yes
+UsePrivilegeSeparation no
#PermitUserEnvironment no
Compression no
ClientAliveInterval 15

The entire patch for the changes described here is on pastebin: PATCH: Configure sshd in Poky.

Cross-Develop Applications

As an application developer, I want to dross-develop applications on my PC and run them on the embedded system.

One of the best things about Yocto/Open Embedded is that it makes the toolchain easy. No more rooting around for just the right magic to find a toolchain that will work, OE will build a perfect toolchain every time.

Tools

Again, I first fetch all the files and then make then, simply because I want to see how fast my system is at compiling 🙂

$ time bitbake -c fetchall meta-toolchain-sdk
real 4m34.503s
user 0m27.406s
sys 0m9.317s
$ time bitbake meta-toolchain-sdk
real 65m20.420s
user 126m25.794s
sys 19m43.990s

To install the SDK onto our system, untar it into place. The toolchain expects to be installed into “/opt/poky/1.2”, so be sure you have write privileges to /opt first, and then run this:

$ tar xvfjC tmp/deploy/sdk/poky-eglibc-x86_64-arm-toolchain-gmae-1.2.tar.bz2 /

Libraries

To run applications on the target, we need the standard libraries on the target. The easiest way to get them there is to add task-core-standalone-sdk-target to core-image-minimal.bb. Then, edit task-core-standalone-sdk-target to include the libraries needed in our standalone target sdk. In this case, it’s ONLY libgcc and libstdc++. The -dev packages are extraneous and add an additional 60MB to the image. So I’ve removed them from task-core-standalone-sdk-target:

The patch to do this is on pastebin, at PATCH: Add custom standalone sdk.

Openssh

Build core-image-minimal again, and you’ll have an image ready to run our own applications.

Building Applications

Now here is the ‘hello world’ of a cross-developed C++ application. I recommend doing the cross-development in a DIFFERENT shell from the one used to run bitbake, because the cross-development environment sets up its own environment variables, and we don’t want the two to conflict.

hello-world.cpp:

#include <iostream>
using namespace std;
int main()
{
cout << 'Hello, ARM' << endl;
return 0;
}

Makefile:

hello-world : hello-world.o
$(CXX) $(LDFLAGS) $< -o $@
clean:
@rm -f hello-world hello-world.o

make:

$ source /opt/poky/1.2/environment-setup-armv5te-poky-linux-gnueabi
$ make
arm-poky-linux-gnueabi-g++ -march=armv5te -marm -mthumb-interwork -mtune=arm926ej-s --sysroot=/opt/poky/1.2/sysroots/armv5te-poky-linux-gnueabi -march=armv5te -marm -mthumb-interwork -mtune=arm926ej-s --sysroot=/opt/poky/1.2/sysroots/armv5te-poky-linux-gnueabi -c -o hello-world.o hello-world.cpp
arm-poky-linux-gnueabi-g++ --sysroot=/opt/poky/1.2/sysroots/armv5te-poky-linux-gnueabi hello-world.o -o hello-world

We can copy that up to the target using scp now that openssh is set up.

$ scp hello-world root@192.168.7.2:
hello-world 100% 8831 8.6KB/s 00:00

And run it there.

Optimize Poky

I dont want to waste disk space, boot time, and memory on unused features. This is an area I’ve just started to explore. Darren Hart gave a great talk on doing this: Tuning Embedded Linux.

Introduction

wolfSSL maintains a Yocto and OpenEmbedded (OE) layer including recipes for wolfSSL products (wolfSSL, wolfSSH, wolfMQTT, wolfTPM), examples, and support for building other Open Source recipes with wolfSSL support. This layer is named “meta-wolfssl”, and is available on GitHub. This document will describe how to easily get started with wolfSSL for Yocto or OpenEmbedded.

meta-wolfssl:
https://www.github.com/wolfssl/meta-wolfssl

Why use wolfSSL?

The wolfSSL embedded SSL/TLS library is a perfect fit for securing Yocto and OpenEmbedded based applications. wolfSSL has been optimized for low memory use and high performance, is extremely portable, supports current standards up to TLS 1.3 and DTLS 1.2, and can be easily combined with any of wolfSSL’s other products (SSH, MQTT, TPM, etc). wolfSSL also maintains a low CVE/vulnerability track record due to a thorough development and nightly testing cycle, providing users with the best tested cryptography available today.

Getting Started

Environment, Build, and Image Setup

Adding the “meta-wolfssl” layer to your build, you will need to set up your development environment and image build directory. If you are an experienced Yocto/OE user, feel free to skip this section. If you need a good starting point, the Yocto Project provides a good Quick Build / Getting Started Guide.

Clone the 'meta-wolfssl' Layer

You may want to place this alongside your other build layers for easy organization. In this guide, the example commands will assume your working Yocto/OE directory is located at “~/poky”. This is the directory that the Yocto Project Quick Build instructions use. Please change this to match your build directory.

Add “meta-wolfssl” to the Layer Configuration File

Insert the “meta-wolfssl” layer location into your build’s bblayers.conf file, in the BBLAYERS section:

Add “meta-wolfssl” to Your Project

Edit your build’s local.conf file, adding the recipes from “meta-wolfssl” that you want to install and use in your project to the IMAGE_INSTALL_append variable. This will include and install the selected libraries.

For example, to install only the wolfSSL library:

To install wolfSSL, wolfSSH, wolfMQTT, and wolfTPM:

To install wolfSSL and the wolfCrypt test and benchmark applications:

Once your image has been built, the default location for the above libraries will be in the “/usr/lib” directory. The default location for the wolfCrypt test and benchmark applications will be in the “/usr/bin” directory.

Compiling “meta-wolfssl” Recipes Individually

Once the “meta-wolfssl” layer has been added to your BBLAYERS collection, you can build individual recipes from the layer using the bitbake command to make sure they compile successfully.

Customizing the wolfSSL Library Build Configurations

The default wolfSSL product recipes are set up to compile the default library configurations. These default configurations are equivalent to running a normal “./configure” on the library if you were compiling it using the Autoconf tools. wolfSSL, and other libraries, have lots of available configure (enable/disable) options that can be used to customize the library feature set. Users commonly want to enable/disable features or algorithms to meet requirements, reduce memory usage, or optimize performance.

Finding and Viewing Library Configure Options

To see a list of available library configure options, either look at the product manual (ex: wolfSSL User Manual), or use the “./configure --help” command in the root of the wolfSSL library directory to list available configure options.

In order to have access to a library’s configure script, you need to be in the source directory of the product. You can either download the product from the wolfSSL website or browse to the temporary source directory that bitbake has created for you as part of the recipe build.

Using the temporary source directory created by the bitbake command, the configure help options could be viewed by running commands similar to below.

Now that you have found the list of possible enable options, the next step is to modify your build of the wolfSSL libraries to include the desired features.

Modifying Library Recipe Build to Include Additional Features

Although the library recipes can be edited directly, it is recommended that users create a .bbappend file in their application layers which override or edit desired wolfSSL library recipe configuration. This makes it easier to update when changes to the upstream “meta-wolfssl” layer get made.

For example, let’s say we have an application that wanted to use the wolfSSL library and needed SHA-512 support. To meet this requirement, the wolfSSL library recipe needs to be modified to compile in SHA-512 support (via the “--enable-sha512” configure option).

First, create a .bbappend file in the application layer which will append configuration information to the upstream wolfSSL recipe:

Inside this .bbappend file, use the EXTRA_OECONF variable to add additional configure options to the wolfSSL library build. To enable SHA-512:

Or, another example might be enabling support for TLS 1.3:

Make Sure .bbappend Files Get Found by the Application

Depending on where the .bbappend file gets placed in your application layer, you may need to edit the BBFILES variable in your layer’s “conf/layer.conf” file to match the directory structure where the .bbappend file is located.

The BBFILES variable will be specific to your application layer’s structure. General structure may be similar to:

wolfSSL Example Application Recipes

The “meta-wolfssl” layer includes several example application recipes, for testing and example purposes. The current example recipes include:

  • wolfCrypt test application (depends on wolfssl)
  • wolfCrypt benchmark application (depends on wolfssl)

The recipe files for these applications are located at:

These can be compiled individually with bitbake:

To install these applications into an image, edit the project’s “build/conf/local.conf” file and add them to the “IMAGE_INSTALL_append” variable. For example:

Yocto Openssh Permitrootlogin

When the image is built, these examples will then be installed by default to the “/usr/bin” directory.

Excluding Recipes from the Build

Not all users will want to compile all wolfSSL product, example, and support recipes included in the “meta-wolfssl” layer. Recipes can be excluded from the build by simply deleting their respective directories from the “meta-wolfssl” layer.

For example, to delete the wolfTPM recipe:

Or, to delete the example applications:

Support and Maintenance

Please email the wolfSSL support team (support@wolfssl.com) with any questions or maintenance requests to the “meta-wolfssl” layer.

License

wolfSSL, wolfMQTT, and wolfTPM are open source and dual licensed under both the GPLv2 and a standard commercial license. wolfSSH is open source and dual licensed under both the GPLv3 and a standard commercial license.

Yocto Openssh Instead Of Dropbear

For commercial license questions, please contact wolfSSL at licensing@wolfssl.com.