This is a first attempt to describe how to test the new Nut/OS TLS implementation.
Note: Currently only the server side of TLS 1.2 is implemented. TLS 1.2 is the most recent (August 2008) version of Transport Layer Security. Although the standard is released a few years ago, Browser developers started implementing it just quite recently, so it is not wide spread.
Our implementation was tested with:
- IE 8(?)
- Opera 12.02 (Linux & Windows)
Note: The current implementation is quite slow (it takes about 11.7 seconds on the AT91SAM7X) to do the RSA computations for the handshake. So be a little bit patient with the connection process.
Note: This only works for ARM Controllers, AVR are (currently) not supported (the note above may be a reason why).
In Opera and IE you have to explicitly enable TLS 1.2 in the security settings (usually under "advanced settings" or similar).
You also have to install the recent version of arm-crypto-lib (from Das Labor) (link to the instruction will be inserted when instructions are written).
To build and test the Test-Server (from 'tls' in the application directory) you may follow the following instructions.
Note: The instructions are currently for GNU/Linux systems only. They might work with Windows or Mac OS X but it is not tested. The develop/testing machine runs on a current ArchLinux installation.
- 1 Prepare
- 2 Build Crypto-Lib
- 3 Build Nut/OS and Testserver
- 4 Testing the Test-Server
- 5 Generating your own certificate
We will create a special directory for our experiments, let us call it nuttls_test_space
mkdir nuttls_test_space cd nuttls_test_space
Here we create two more directorys, one for nutos and one for the crypto library
mkdir nut cryptolib
Step 1 - get the source
cd cryptolib git clone git://das-labor.org/users/bg/arm-crypto-lib .
This may take some time (it has to download ~260MiB of data).
Step 2 - configure
Normally there should be nothing to configure. But you should check that the build options defined in Makefile_sys_conf.inc and Makefile_arm7tdmi_conf.inc match the build options for Nut/OS (especially the ABI).
Step 3 - build
It should be as easy as running:
make -f Makefile_arm7tdmi lib
You should now have a library (bin/arm7tdmi_generic/lib/libcrypto.a).
Step 4 - install
First you have to install the library. Therefore copy the file bin/arm7tdmi_generic/lib/libcrypto.a into the library directory of your toolchain (for example /usr/arm-elf/lib/ on my system) and change the permissions so that your user can read it.
sudo cp bin/arm7tdmi_generic/lib/libcrypto.a /usr/arm-elf/lib/ <br> chmod 664 /usr/arm-elf/lib/libcrypto.a
Next you have to install the header-files. You can use the script install_headers.sh but have to adjust the PREFIX variable (line 3) to match the header directory of your toolchain.
sudo sh install_headers.sh
Build Nut/OS and Testserver
Step 1 - get the source
Then we check out the current nuttls-development-tree
cd nut <br> svn co https://ethernut.svn.sourceforge.net/svnroot/ethernut/branches/devnut_tls .
Step 2 - configure the source
If you have not installed nutconf or qnutconf before you should do it now. [] may shows you how.
So we are still in our nut directory (you should avoid to confuse it with the nut directory we just got with our check-out).
Will start the graphical configuration interface. It will ask you for your configuration file and you should select the one matching your board (current tests run on an AT91SAM7X-EK, if you are lucky enough to have this board you may directly select tls_at91sam7x-ek.conf).
You should at least adjust the Main Thread Stack Size to 2048 bytes (the RSA computation takes a lot of stack).
Nut/OS Components -> RTOS Kernel -> Multithreading -> Main Thread Stack Size -> 2048
You may adjust other items, like your compiler, libc, ...
For our purposes we set the nut build directory to nut_build and the application (sample) directory to nut_app in the "Settings Menu" ( Edit -> Settings).
Now you have to build Nut/OS:
Build -> Build Nut/OS
And create the app directory:
Build -> Create Sample Directory
Step 3 - build the TLS Test-Server
cd nut_app/tls <br> make
You now should have working binaries. You may be able to use
to flash your binary to your board. This did not work for me, so if you have an AT91SAM7X-EK you may instead run
Testing the Test-Server
First you have to identify which IP-Address is assigned to your board by the DHCP-Server. To get this information you may query your DHCP-Server, or get it from the Debug output from your board (you did connect the UART/RS232 interface to the debug port, didn't you?).
You should see the following output (or at least quite a similar one, since this changes during development):
Nut/OS 18.104.22.168 TLS Server Sample 0.1.0 Configure eth0...OK Run 'gnutls-cli 192.168.192.243 443' to connect to this server Register UROM file system...OK. spawning thread: tls_0 Waiting for a tls client... spawning thread: tls_1 Waiting for a tls client... spawning thread: tls_2 Waiting for a tls client...
Here our address is 192.168.192.243, this will be different on your board.
Now you can add a hostname for this IP-Address to your machines configuration
sudo echo <board-ip> nuttls_test_system >> /etc/hosts
It is now time to connect via TLS. I recommend using the command-line utility from GnuTLS:
gnutls-cli --x509cafile cert/nuttls_test_system.cert nuttls_test_system
Now the following should appear on your terminal: Processed 1 CA certificate(s). Resolving 'nuttls_test_system'... Connecting to '192.168.192.243:443'... - Peer's certificate is trusted - The hostname in the certificate matches 'nuttls_test_system'. - Session ID: E4:0E:C7:B0 - Certificate type: X.509 - Got a certificate list of 1 certificates. - Certificate info: - subject `C=DE,O=egnite GmbH,ST=NRW,CN=Daniel Otte', issuer `C=DE,O=egnite GmbH,ST=NRW,CN=Daniel Otte', RSA key 512 bits, signed using RSA-SHA256, activated ` 2012-06-18 17:09:27 UTC', expires `2013-06-18 17:09:27 UTC', SHA-1 fingerprint `6ff3f09462e388468f96eaef941baf95c169be83' Public Key Id: 4b16eff5669cf1ed071cc55eb3e52953fc23c5e6 Public key's random art: +--[ RSA 512]----+ | o. | | B=| | . =+B| | o +.E+| | S . ..=..| | o o . oo+.| | . . *.o| | o ..| | o| +-----------------+ - Version: TLS1.2 - Key Exchange: RSA - Cipher: AES-128-CBC - MAC: SHA256 - Compression: NULL - Handshake was completed - Simple Client Mode:
You have now opened a direct connection to the board (it a little bit like telnet). You can now start an HTTP-Request (note the blank line afte the GET ... line)
GET / HTTP
The Server should respond with
HTTP/1.1 200 Ok Server: Ethernut 22.214.171.124 Content-Type: text/html Content-Length: 59 Connection: close <html> <head></head> <body> <h1>Works</h1> </body> </html>
And then it should close the connection.
Generating your own certificate
For this steps you currently need a working C-Compiler (gcc is used in the examples) and a working ruby environment.
You may be interested in getting your own certificate on the board. There are many good tutorials how to set up a PKI so we will not go to much into detail here. So for now we assume you have a RSA certificate in DER form and a matching key in text form as shown in the example below (created with certtool from gnuTLS):
Public Key Info: Public Key Algorithm: RSA Key Security Level: Low modulus: 00:c4:04:46:32:2b:18:eb:56:d4:01:7a:4e:db:b7: 50:05:34:65:64:07:26:86:b8:d0:2b:d9:d5:3d:35: d8:4e:77:f8:6b:21:9a:be:a5:6f:4c:ef:82:1c:58: 36:7a:f1:ba:81:1e:32:8c:d4:5c:dc:df:6e:13:b6: dc:d9:49:0a:25: public exponent: 01:00:01: private exponent: 00:c2:a4:0f:e4:3f:41:66:67:78:eb:e2:bc:ad:96: b0:c2:0a:4e:67:ee:65:c6:3f:7c:8f:1e:a6:8d:3a: 8b:89:15:fd:8d:11:aa:f8:ad:a7:cf:5c:c7:86:11: 83:cc:f8:37:16:14:a5:3e:53:8b:ce:c4:42:46:bf: 7f:b0:11:d7:bd: prime1: 00:c4:97:6d:6a:04:19:0c:69:b0:16:63:74:73:d2: cf:21:2c:00:47:6e:4c:88:a0:8b:d6:69:25:e2:82: 00:ce:db: prime2: 00:ff:40:60:d2:35:bb:a0:18:fa:2a:aa:65:bc:d5: 35:65:fb:c0:f6:20:4b:33:65:a2:97:43:d7:04:7b: e6:5a:ff: coefficient: 00:9a:2b:48:98:ac:76:06:a4:05:f6:c6:ec:0f:70: c8:47:44:98:0f:1f:ec:26:61:f7:04:2c:7f:2d:55: b6:ce:67: exp1: 54:c6:4b:fb:6c:9a:f4:9c:5a:bf:bc:d1:89:e4:bd: 47:3b:b7:3f:16:54:50:92:92:da:b9:eb:09:5b:30: 48:03: exp2: 31:8c:9b:be:f2:b3:53:66:c5:d9:56:6e:9d:73:7e: 04:28:14:d3:32:7d:a6:a2:8a:27:77:01:dc:5a:f8: e2:9d: ...
The next step is compiling the cert-merge tool in the directory cert:
cd cert gcc -o cert-merge cert-merge.c
You are now able to create new certificate-binary-blobs. If nuttls_test_system.cert.der is your DER-certificate you can use
./cert-merge nuttls_test_system.cert.tls nuttls_test_system.cert.der
to create a binary blob for the nutTLS system. To include this blob you may like to create an elf-file like this:
arm-elf-objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents \ -I binary -O elf32-littlearm nuttls_test_system.cert.tls \ nuttls_test_system.cert.tls.elf
Now you should have nuttls_test_system.cert.tls.elf ready for linking into your project. If you changed the input file name for the elf-file you should adjust the Macros CERT_BLOB_START, CERT_BLOB_END and CERT_BLOB_SIZE in tls_handshake.c as they are based on the file name.
What is left is inclusion of the key. The key is transformed into C-source-code by convert-key.rb. convert-key.rb is a ruby script which transforms a RSA key given in the text form shown above into C-code. If your key file is named nuttls_test_system.key, you may use the following command:
ruby convert-key.rb nuttls_test_system.key > server.key.c
If you copy both new created files (nuttls_test_system.cert.tls.elf and server.key.c) in the projects directory and recreate the project:
make clean all
You should have a working binary with your certificate.