CyaSSL example using x509 certs and DTLS over ethernet.
Dependencies: EthernetInterface NTPClient cyassl-lib mbed-rtos mbed-src CyaSSL_DTLS_Ethernet
Dependents: CyaSSL_DTLS_Ethernet
Testing DTLS out
To test this client you need to setup a server and use the correct CA certificate, server certificate, and server private key. This will allow the client to authenticate to the server, and enable the server to authenticate the client. The server can authenticate the client because the test program includes a device certificate signed by the server CA.
The server certificate and and CA certificate are identical as this is a self-signed certificate:
-----BEGIN CERTIFICATE----- MIIClTCCAf6gAwIBAgICEREwDQYJKoZIhvcNAQEFBQAwZzELMAkGA1UEBhMCR0Ix EjAQBgNVBAgMCUJlcmtzaGlyZTEQMA4GA1UEBwwHTmV3YnVyeTERMA8GA1UECgwI Vm9kYWZvbmUxDDAKBgNVBAsMA1ImRDERMA8GA1UEAwwIRE1TZXJ2ZXIwHhcNMTMw OTAzMTQwNjA4WhcNMjMwNzEzMTQwNjA4WjBnMQswCQYDVQQGEwJHQjESMBAGA1UE CAwJQmVya3NoaXJlMRAwDgYDVQQHDAdOZXdidXJ5MREwDwYDVQQKDAhWb2RhZm9u ZTEMMAoGA1UECwwDUiZEMREwDwYDVQQDDAhETVNlcnZlcjCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAupWZHm51RbMkEkvKAvglM96BcWVScxW7KaXFhm1Artt1 1Vm5KTC0rI+0kiG54kxhvY7euWeUcQqJKHxUTFjUWv8TcJrzmjIe5EthipLpdN+V /PJCO/FiLXSiykQsC+VhyU8BKNYrpspyiQ109KPoybH8kK7W2IXf2d9AaLrzcgUC AwEAAaNQME4wHQYDVR0OBBYEFKonGm+IcowtLcJaxXSCpUTRPaMVMB8GA1UdIwQY MBaAFKonGm+IcowtLcJaxXSCpUTRPaMVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN AQEFBQADgYEAfThlu2u73hm3quZJX57joMRn/N+l2KY4q16YI+gZIoJlLF/uIZw6 4OuxfKNfIvKvCL54LQ+/plh+8CzsmZdjdV9S/1+Jefe+RhEogjSvFjs2oyVaMCjZ OxWujvZJ3XdhpXZJsdnEx4rgmHij3es3SzarTSjPVW8MpBU4H8NKlWI= -----END CERTIFICATE-----
The server private key is as follows:
-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALqVmR5udUWzJBJL ygL4JTPegXFlUnMVuymlxYZtQK7bddVZuSkwtKyPtJIhueJMYb2O3rlnlHEKiSh8 VExY1Fr/E3Ca85oyHuRLYYqS6XTflfzyQjvxYi10ospELAvlYclPASjWK6bKcokN dPSj6Mmx/JCu1tiF39nfQGi683IFAgMBAAECgYEAuAFGQtud7YHQRfbWHv2G+tMp BqJsoDBDJrxjwsFFs+ucFi5oyzVMSI1j/2UhQwoerekSvvdmTeCdCP8rxysnJ3MG vepBkUXZ9kek7qZ561JC6qLZNcTeVc/R1rxMsFZSV/Zuzr7KFG47J/Di15GxGoui x4fRE9ww0coC8PDWbaECQQDgKP48PD2gNaD2jjqd/xNki2kXP9PE1AAnevVaEidS ceOKXgqx7qGYrN1+NFnRGwJhUSoicmUQeDKkC9CU/5UpAkEA1RZCT9M8lWpqx60d oZlF9I3oOoQxXrx4RgoF+2y1tT+C7nUwmeYk2mEi/Gat9/NtKz/J9Tlwu3/Ef9eB G7lVfQJAdvzLl2XSwIw3GSl+bAfOX3yxGCpFWyG9wzc9rcYdIWJbCkPJIZIuLUD1 gdyAIMNZjBbtasOWahujpfivi6fvoQJAHRIdV+CculG7YaR3j21mwtd9YEZaqe8S hZOmf0e0fpa8mSW5zLU+P+DSshacE2DNewIH3oHIpHvo5fwTrCGbzQJAWaFq9L9C lAgoPfuKjKQ0RJ8M+lDVOZo/Okl0VtrU/Z5fQm+yR4Lb+o1iogYjgjvdOmoMkPtb Q/xu4c1qn2ksnA== -----END PRIVATE KEY-----
Both the certificate and the private key are in PEM format. It is worth noting that all the certificates and keys on the device are in DER format to save space. You might be wondering how to easily get PEM keys and certs into a format suitable for the mbed, well it's easy, you can just use the openssl tools to convert, and then xxd to get a hex sequence which you can put into an array. To convert a cert, use the following command:
openssl x509 -in cert.pem -outform DER | xxd -i
This will dump the x509 cert in DER format and pipe it to xxd, where the -i switch is used to convert the byte sequence into c-include style. All it really does is dump the bytes in hexadecimal, you still need to wrap it in an array like this:
const static unsigned char deviceCertificate[] = { OUTPUT OF ABOVE }; const static int deviceCertificateLength = sizeof(deviceCertificate);
For converting keys, the command is the same buy you use the rsa subcommand of openssl (or dsa if you used DSA keys):
openssl rsa -in key.pem -outform DER | xxd -i
In anycase, to use the PEM files with the CyaSSL server, download the CyaSSL example server from here: http://yassl.com/yaSSL/download/downloadForm.php. Configure it with debugging and dtls before compiling (I've also enabled PSK because I'm testing that):
./configure --enable-psk --enable-debug --enable-dtls
Then do
make
Now, the cyaSSL server needs the PEM certificates above to work with those setup on the mbed device, but it is particular about where these PEM certs are found. You need to put them in the certs directory in the root of the unzipped code (it seems to ignore flags which point it elsewhere).
And for some reason cyaSSL calls the CA certificate the "client-cert.pem", so copy the server certificate above into "certs/client-cert.pem" and also copy it into "certs/server-cert.pem". Copy the server private key into "certs/server-key.pem".
Now change directory into example/server/ and run the server like this:
./server -u -b -f
These flags are -u for UDP i.e DTLS, -b to bind to all interfaces, and -f to group messages (fewer packets). For some reason this last flag is needed to work properly with the mbed.
You should now be able to fire up the mbed, change the code to point to your server, and see the handshake and test messages go back and forth. You can see it works because you should see the message "I hear you fa shizzle!" on the mbed (this is the message they define), and you should see the message "onion" received on the server.
Generating your own keys and certificates
OK so you want to generate your own self-signed certificate for your server and device. Great, but I'm too busy/lazy to write a detailed tutorial right now. Instead I've created you a shell script that randomly generates a new self-signed CA/server-cert and uses this to sign a device certificate.
The device certificate and private key are placed into a directory called mbed/certs where as the server certs are placed in server/certs. You'll have to read up on these commands to work out how to generate and sign more device certs, and how to change options etc. HTH.
#!/bin/sh CA_KEY_FILE=ca_key.pem CA_KEY_FORMAT=PEM CA_KEY_ALGORITHM=rsa CA_KEY_BITS=1024 # 1. Make a key for the CA (in this case the server) echo Generating $CA_KEY_ALGORITHM key: $CA_KEY_FILE openssl genpkey \ -out $CA_KEY_FILE \ -outform $CA_KEY_FORMAT \ -algorithm $CA_KEY_ALGORITHM \ -pkeyopt rsa_keygen_bits:$CA_KEY_BITS echo DONE # extract public key (for vanity) openssl pkey \ -in $CA_KEY_FILE \ -pubout \ -out $CA_KEY_FILE.pub # 2. Make a self signed certificate for the CA (trusted certificate) # req - PKCS#10 certificate request and certificate generating utility. CA_CERT_EXPIRY=3600 CA_CERT_SERIAL=0x1111 CA_CERT_FILE=ca_cert.pem CA_CERT_REQ=ca_cert_req.pem CA_ID=DMServer echo Generating self signed root CA certificate: $CA_CERT_FILE openssl req \ -new \ -key $CA_KEY_FILE \ -days $CA_CERT_EXPIRY \ -set_serial $CA_CERT_SERIAL \ -subj "/C=GB/ST=Berkshire/L=Newbury/O=Vodafone/OU=R&D/CN=$CA_ID" \ -out $CA_CERT_FILE \ -x509 \ -verbose echo DONE. # 3. Make a key for the device DEV_KEY_FILE=dev_key.pem DEV_KEY_FORMAT=PEM DEV_KEY_ALGORITHM=rsa DEV_KEY_BITS=1024 echo Generating $DEV_KEY_ALGORITHM key: $DEV_KEY_FILE openssl genpkey \ -out $DEV_KEY_FILE \ -outform $DEV_KEY_FORMAT \ -algorithm $DEV_KEY_ALGORITHM \ -pkeyopt rsa_keygen_bits:$DEV_KEY_BITS echo DONE # extract public key (for vanity) openssl pkey \ -in $DEV_KEY_FILE \ -pubout \ -out $DEV_KEY_FILE.pub # 4. Make a certificate request for the device DEV_CERT_EXPIRY=3600 DEV_CERT_SERIAL=2222 DEV_CERT_REQ_FILE=dev_cert_req.pem DEV_CERT_FILE=dev_cert.pem DEV_ID=Device1 echo Generating certificate request for device: $DEV_CERT_REQ_FILE openssl req \ -new \ -key $DEV_KEY_FILE \ -days $DEV_CERT_EXPIRY \ -set_serial $DEV_CERT_SERIAL \ -subj "/C=GB/ST=Berkshire/L=Newbury/O=Vodafone/OU=R&D/CN=$DEV_ID" \ -out $DEV_CERT_REQ_FILE \ -verbose echo DONE. # 5. Sign the device certificate using the root CA certificate echo Creating directories and other stuff I really wish was not needed mkdir -p demoCA/newcerts touch demoCA/index.txt echo $DEV_CERT_SERIAL > demoCA/serial echo DONE. # do the actual signing echo Signing certificate request $DEV_CERT_REQ_FILE with certificate $CA_CERT_FILE openssl ca \ -in $DEV_CERT_REQ_FILE \ -out $DEV_CERT_FILE \ -days $DEV_CERT_EXPIRY \ -keyfile $CA_KEY_FILE \ -cert $CA_CERT_FILE \ -batch \ -verbose echo DONE. # 6 convert this stuff into a format suitable for mbed echo Creating mbed include files MBED_DIR=mbed/certs mkdir -p $MBED_DIR # private key OUT=$MBED_DIR/device_private_key.h echo "#pragma once" > $OUT echo "const static unsigned char devicePrivateKey[] = {" >> $OUT openssl $DEV_KEY_ALGORITHM -in $DEV_KEY_FILE -outform DER | xxd -i >> $OUT echo "};" >> $OUT echo "const static int devicePrivateKeyLength = sizeof(devicePrivateKey);" >> $OUT # device cert OUT=$MBED_DIR/device_certificate.h echo "#pragma once" > $OUT echo "const static unsigned char deviceCertificate[] = {" >> $OUT openssl x509 -in $DEV_CERT_FILE -outform DER | xxd -i >> $OUT echo "};" >> $OUT echo "const static int deviceCertificateLength = sizeof(deviceCertificate);" >> $OUT # CA cert OUT=$MBED_DIR/root_certificate.h echo "#pragma once" > $OUT echo "const static unsigned char rootCertificate[] = {" >> $OUT openssl x509 -in $CA_CERT_FILE -outform DER | xxd -i >> $OUT echo "};" >> $OUT echo "const static int rootCertificateLength = sizeof(rootCertificate);" >> $OUT echo DONE. # create (copy) the server files for CyaSSL echo Creating PEM file structure of CyaSSL server OUT=server/certs mkdir -p $OUT cp $CA_CERT_FILE $OUT/client_cert.pem cp $CA_CERT_FILE $OUT/server_cert.pem cp $CA_KEY_FILE $OUT/server_key.pem echo DONE.
History
Added DN verification.
2013-09-19, by ashleymills [Thu, 19 Sep 2013 13:26:15 +0000] rev 4
Added DN verification.
Cleaned some things up. Removed some cellular stuff.
2013-09-19, by ashleymills [Thu, 19 Sep 2013 13:07:53 +0000] rev 3
Cleaned some things up. Removed some cellular stuff.
No reason
2013-09-05, by ashleymills [Thu, 05 Sep 2013 13:02:39 +0000] rev 2
No reason
Init;
2013-09-05, by ashleymills [Thu, 05 Sep 2013 13:01:24 +0000] rev 1
Init;
Initial commit.
2013-09-05, by ashleymills [Thu, 05 Sep 2013 10:38:56 +0000] rev 0
Initial commit.