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.
Committer:
ashleymills
Date:
Thu Sep 05 10:38:56 2013 +0000
Revision:
0:00174d07d068
Child:
3:48795329999a
Initial commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:00174d07d068 1 #define __DEBUG__ 4 //Maximum verbosity
ashleymills 0:00174d07d068 2 #ifndef __MODULE__
ashleymills 0:00174d07d068 3 #define __MODULE__ "main.cpp"
ashleymills 0:00174d07d068 4 #endif
ashleymills 0:00174d07d068 5
ashleymills 0:00174d07d068 6 #define DEBUG_CYASSL 1
ashleymills 0:00174d07d068 7 #include "bsd_socket.h"
ashleymills 0:00174d07d068 8 #include "mbed.h"
ashleymills 0:00174d07d068 9 #include "rtos.h"
ashleymills 0:00174d07d068 10 #include "dbg.h"
ashleymills 0:00174d07d068 11 #include "cyassl/ssl.h"
ashleymills 0:00174d07d068 12 //#include "VodafoneUSBModem.h"
ashleymills 0:00174d07d068 13 #include "EthernetInterface.h"
ashleymills 0:00174d07d068 14 #include "NTPClient.h"
ashleymills 0:00174d07d068 15
ashleymills 0:00174d07d068 16 #include "logging.h"
ashleymills 0:00174d07d068 17
ashleymills 0:00174d07d068 18 #define APN_PAYG
ashleymills 0:00174d07d068 19
ashleymills 0:00174d07d068 20 #ifdef APN_GDSP
ashleymills 0:00174d07d068 21 #define APN "ppinternetd.gdsp"
ashleymills 0:00174d07d068 22 #define APN_USERNAME ""
ashleymills 0:00174d07d068 23 #define APN_PASSWORD ""
ashleymills 0:00174d07d068 24 #endif
ashleymills 0:00174d07d068 25
ashleymills 0:00174d07d068 26 #ifdef APN_CONTRACT
ashleymills 0:00174d07d068 27 #define APN "internet"
ashleymills 0:00174d07d068 28 #define APN_USERNAME "web"
ashleymills 0:00174d07d068 29 #define APN_PASSWORD "web"
ashleymills 0:00174d07d068 30 #endif
ashleymills 0:00174d07d068 31
ashleymills 0:00174d07d068 32 #ifdef APN_PAYG
ashleymills 0:00174d07d068 33 #define APN "smart"
ashleymills 0:00174d07d068 34 #define APN_USERNAME "web"
ashleymills 0:00174d07d068 35 #define APN_PASSWORD "web"
ashleymills 0:00174d07d068 36 #endif
ashleymills 0:00174d07d068 37
ashleymills 0:00174d07d068 38 #include "certs/device_certificate.h"
ashleymills 0:00174d07d068 39 #include "certs/device_private_key.h"
ashleymills 0:00174d07d068 40 #include "certs/root_certificate.h"
ashleymills 0:00174d07d068 41 /*
ashleymills 0:00174d07d068 42 static INLINE unsigned int my_psk_client_cb(CYASSL* ssl, const char* hint,
ashleymills 0:00174d07d068 43 char* identity, unsigned int id_max_len, unsigned char* key,
ashleymills 0:00174d07d068 44 unsigned int key_max_len)
ashleymills 0:00174d07d068 45 {
ashleymills 0:00174d07d068 46 (void)ssl;
ashleymills 0:00174d07d068 47 (void)hint;
ashleymills 0:00174d07d068 48 (void)key_max_len;
ashleymills 0:00174d07d068 49
ashleymills 0:00174d07d068 50 DBG("PSK client callback callled.");
ashleymills 0:00174d07d068 51
ashleymills 0:00174d07d068 52 // identity is OpenSSL testing default for openssl s_client, keep same
ashleymills 0:00174d07d068 53 strncpy(identity, "Client_identity", id_max_len);
ashleymills 0:00174d07d068 54
ashleymills 0:00174d07d068 55
ashleymills 0:00174d07d068 56 // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
ashleymills 0:00174d07d068 57 // unsigned binary
ashleymills 0:00174d07d068 58 key[0] = 26;
ashleymills 0:00174d07d068 59 key[1] = 43;
ashleymills 0:00174d07d068 60 key[2] = 60;
ashleymills 0:00174d07d068 61 key[3] = 77;
ashleymills 0:00174d07d068 62
ashleymills 0:00174d07d068 63 return 4; // length of key in octets or 0 for error
ashleymills 0:00174d07d068 64 }
ashleymills 0:00174d07d068 65
ashleymills 0:00174d07d068 66
ashleymills 0:00174d07d068 67 static INLINE unsigned int my_psk_server_cb(CYASSL* ssl, const char* identity,
ashleymills 0:00174d07d068 68 unsigned char* key, unsigned int key_max_len)
ashleymills 0:00174d07d068 69 {
ashleymills 0:00174d07d068 70 (void)ssl;
ashleymills 0:00174d07d068 71 (void)key_max_len;
ashleymills 0:00174d07d068 72
ashleymills 0:00174d07d068 73
ashleymills 0:00174d07d068 74 DBG("PSK server callback called.");
ashleymills 0:00174d07d068 75
ashleymills 0:00174d07d068 76 // identity is OpenSSL testing default for openssl s_client, keep same
ashleymills 0:00174d07d068 77 if (strncmp(identity, "Client_identity", 15) != 0)
ashleymills 0:00174d07d068 78 return 0;
ashleymills 0:00174d07d068 79
ashleymills 0:00174d07d068 80 // test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
ashleymills 0:00174d07d068 81 // unsigned binary
ashleymills 0:00174d07d068 82 key[0] = 26;
ashleymills 0:00174d07d068 83 key[1] = 43;
ashleymills 0:00174d07d068 84 key[2] = 60;
ashleymills 0:00174d07d068 85 key[3] = 77;
ashleymills 0:00174d07d068 86
ashleymills 0:00174d07d068 87 return 4; // length of key in octets or 0 for error
ashleymills 0:00174d07d068 88 }
ashleymills 0:00174d07d068 89 */
ashleymills 0:00174d07d068 90
ashleymills 0:00174d07d068 91 sockaddr_in bindAddr,serverAddress;
ashleymills 0:00174d07d068 92
ashleymills 0:00174d07d068 93 bool connectToSocketUDP(char *ipAddress, int port, int *sockfd) {
ashleymills 0:00174d07d068 94 *sockfd = -1;
ashleymills 0:00174d07d068 95 // create the socket
ashleymills 0:00174d07d068 96 if((*sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
ashleymills 0:00174d07d068 97 DBG("Error opening socket");
ashleymills 0:00174d07d068 98 return false;
ashleymills 0:00174d07d068 99 }
ashleymills 0:00174d07d068 100 socklen_t sockAddrInLen = sizeof(struct sockaddr_in);
ashleymills 0:00174d07d068 101
ashleymills 0:00174d07d068 102 // bind socket to 11111
ashleymills 0:00174d07d068 103 memset(&bindAddr, 0x00, sockAddrInLen);
ashleymills 0:00174d07d068 104 bindAddr.sin_family = AF_INET; // IP family
ashleymills 0:00174d07d068 105 bindAddr.sin_port = htons(11111);
ashleymills 0:00174d07d068 106 bindAddr.sin_addr.s_addr = IPADDR_ANY; // 32 bit IP representation
ashleymills 0:00174d07d068 107 // call bind
ashleymills 0:00174d07d068 108 if(bind(*sockfd,(const struct sockaddr *)&bindAddr,sockAddrInLen)!=0) {
ashleymills 0:00174d07d068 109 DBG("Error binding socket");
ashleymills 0:00174d07d068 110 perror(NULL);
ashleymills 0:00174d07d068 111 }
ashleymills 0:00174d07d068 112
ashleymills 0:00174d07d068 113 INFO("UDP socket created and bound to: %s:%d",inet_ntoa(bindAddr.sin_addr),ntohs(bindAddr.sin_port));
ashleymills 0:00174d07d068 114
ashleymills 0:00174d07d068 115 // create the socket address
ashleymills 0:00174d07d068 116
ashleymills 0:00174d07d068 117 memset(&serverAddress, 0x00, sizeof(struct sockaddr_in));
ashleymills 0:00174d07d068 118 serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
ashleymills 0:00174d07d068 119 serverAddress.sin_family = AF_INET;
ashleymills 0:00174d07d068 120 serverAddress.sin_port = htons(port);
ashleymills 0:00174d07d068 121
ashleymills 0:00174d07d068 122 // do socket connect
ashleymills 0:00174d07d068 123 //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
ashleymills 0:00174d07d068 124 if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
ashleymills 0:00174d07d068 125 shutdown(*sockfd,SHUT_RDWR);
ashleymills 0:00174d07d068 126 close(*sockfd);
ashleymills 0:00174d07d068 127 DBG("Could not connect");
ashleymills 0:00174d07d068 128 return false;
ashleymills 0:00174d07d068 129 }
ashleymills 0:00174d07d068 130 return true;
ashleymills 0:00174d07d068 131 }
ashleymills 0:00174d07d068 132
ashleymills 0:00174d07d068 133 bool connectToSocket(char *ipAddress, int port, int *sockfd) {
ashleymills 0:00174d07d068 134 *sockfd = -1;
ashleymills 0:00174d07d068 135 // create the socket
ashleymills 0:00174d07d068 136 if((*sockfd=socket(AF_INET,SOCK_STREAM,0))<0) {
ashleymills 0:00174d07d068 137 DBG("Error opening socket");
ashleymills 0:00174d07d068 138 return false;
ashleymills 0:00174d07d068 139 }
ashleymills 0:00174d07d068 140
ashleymills 0:00174d07d068 141 // create the socket address
ashleymills 0:00174d07d068 142 sockaddr_in serverAddress;
ashleymills 0:00174d07d068 143 std::memset(&serverAddress, 0, sizeof(struct sockaddr_in));
ashleymills 0:00174d07d068 144 serverAddress.sin_addr.s_addr = inet_addr(ipAddress);
ashleymills 0:00174d07d068 145 serverAddress.sin_family = AF_INET;
ashleymills 0:00174d07d068 146 serverAddress.sin_port = htons(port);
ashleymills 0:00174d07d068 147
ashleymills 0:00174d07d068 148 // do socket connect
ashleymills 0:00174d07d068 149 //LOG("Connecting socket to %s:%d", inet_ntoa(serverAddress.sin_addr), ntohs(serverAddress.sin_port));
ashleymills 0:00174d07d068 150 if(connect(*sockfd, (const struct sockaddr *)&serverAddress, sizeof(serverAddress))<0) {
ashleymills 0:00174d07d068 151 shutdown(*sockfd,SHUT_RDWR);
ashleymills 0:00174d07d068 152 close(*sockfd);
ashleymills 0:00174d07d068 153 DBG("Could not connect");
ashleymills 0:00174d07d068 154 return false;
ashleymills 0:00174d07d068 155 }
ashleymills 0:00174d07d068 156 return true;
ashleymills 0:00174d07d068 157 }
ashleymills 0:00174d07d068 158 /*
ashleymills 0:00174d07d068 159 int handshakeCallback(HandShakeInfo* hinfo) {
ashleymills 0:00174d07d068 160 DBG("Handshake callback called");
ashleymills 0:00174d07d068 161 }
ashleymills 0:00174d07d068 162 int timeoutCallback(TimeoutInfo *tinfo) {
ashleymills 0:00174d07d068 163 DBG("Timeout callback called");
ashleymills 0:00174d07d068 164 }
ashleymills 0:00174d07d068 165 */
ashleymills 0:00174d07d068 166
ashleymills 0:00174d07d068 167
ashleymills 0:00174d07d068 168 DigitalOut myled(LED1);
ashleymills 0:00174d07d068 169 #define INTERFACE EthernetInterface
ashleymills 0:00174d07d068 170
ashleymills 0:00174d07d068 171 void printError(CYASSL *ssl, int resultCode) {
ashleymills 0:00174d07d068 172 int err = CyaSSL_get_error(ssl, resultCode);
ashleymills 0:00174d07d068 173 char errorString[80];
ashleymills 0:00174d07d068 174 CyaSSL_ERR_error_string(err, errorString);
ashleymills 0:00174d07d068 175 DBG("Error: CyaSSL_write %s", errorString);
ashleymills 0:00174d07d068 176 }
ashleymills 0:00174d07d068 177
ashleymills 0:00174d07d068 178 void debugCallback(const int logLevel,const char *const logMessage) {
ashleymills 0:00174d07d068 179 DBG(logMessage);
ashleymills 0:00174d07d068 180 }
ashleymills 0:00174d07d068 181
ashleymills 0:00174d07d068 182
ashleymills 0:00174d07d068 183 int main() {
ashleymills 0:00174d07d068 184 DBG_INIT();
ashleymills 0:00174d07d068 185 DBG_SET_SPEED(115200);
ashleymills 0:00174d07d068 186 DBG_SET_NEWLINE("\r\n");
ashleymills 0:00174d07d068 187 DBG("\r\n\r\n\r\n\r\n");
ashleymills 0:00174d07d068 188
ashleymills 0:00174d07d068 189 int ret = 0;
ashleymills 0:00174d07d068 190
ashleymills 0:00174d07d068 191 // init modem
ashleymills 0:00174d07d068 192 INTERFACE modem;
ashleymills 0:00174d07d068 193 // connnect modem to cellular network
ashleymills 0:00174d07d068 194 DBG("connecting to network interface");
ashleymills 0:00174d07d068 195 //if(modem.connect(APN,APN_USERNAME,APN_PASSWORD)!=0) {
ashleymills 0:00174d07d068 196 // DBG("Error connecting to mobile network");
ashleymills 0:00174d07d068 197 //}
ashleymills 0:00174d07d068 198 modem.init();
ashleymills 0:00174d07d068 199 if(modem.connect(10000)) {
ashleymills 0:00174d07d068 200 DBG("Error initialising ethernet interface");
ashleymills 0:00174d07d068 201 }
ashleymills 0:00174d07d068 202 DBG("Connected to network interface");
ashleymills 0:00174d07d068 203
ashleymills 0:00174d07d068 204 DBG("IP: %s",modem.getIPAddress());
ashleymills 0:00174d07d068 205
ashleymills 0:00174d07d068 206 // need to set the time before doing anything else
ashleymills 0:00174d07d068 207 NTPClient ntp;
ashleymills 0:00174d07d068 208 time_t currentTime = time(NULL);
ashleymills 0:00174d07d068 209 int obtainedTimeSuccessfully = false;
ashleymills 0:00174d07d068 210 // try 100 times and then just force a watchdog reboot
ashleymills 0:00174d07d068 211 for(int i=0; i<100; i++) {
ashleymills 0:00174d07d068 212 obtainedTimeSuccessfully = false;
ashleymills 0:00174d07d068 213
ashleymills 0:00174d07d068 214 if(ntp.setTime("0.pool.ntp.org")==0) {
ashleymills 0:00174d07d068 215 // there is a bug from somewhere which results in a negative timestamp
ashleymills 0:00174d07d068 216 currentTime = time(NULL);
ashleymills 0:00174d07d068 217 if(currentTime>0) {
ashleymills 0:00174d07d068 218 obtainedTimeSuccessfully = true;
ashleymills 0:00174d07d068 219 INFO("Time set successfully, time is now (UTC): %s", ctime(&currentTime));
ashleymills 0:00174d07d068 220 }
ashleymills 0:00174d07d068 221 }
ashleymills 0:00174d07d068 222 if(obtainedTimeSuccessfully) {
ashleymills 0:00174d07d068 223 break;
ashleymills 0:00174d07d068 224 }
ashleymills 0:00174d07d068 225 }
ashleymills 0:00174d07d068 226
ashleymills 0:00174d07d068 227
ashleymills 0:00174d07d068 228 // set SSL method to SSL v3 (TLS v1.2)
ashleymills 0:00174d07d068 229 //CyaSSLv23_client_method();
ashleymills 0:00174d07d068 230
ashleymills 0:00174d07d068 231 CyaSSL_Init();// Initialize CyaSSL
ashleymills 0:00174d07d068 232 if(CyaSSL_Debugging_ON()==0) {
ashleymills 0:00174d07d068 233 DBG("CyaSSL debugging enabled");
ashleymills 0:00174d07d068 234 } else {
ashleymills 0:00174d07d068 235 DBG("CyaSSL debugging not compiled in");
ashleymills 0:00174d07d068 236 }
ashleymills 0:00174d07d068 237
ashleymills 0:00174d07d068 238 CyaSSL_SetLoggingCb(&debugCallback);
ashleymills 0:00174d07d068 239
ashleymills 0:00174d07d068 240
ashleymills 0:00174d07d068 241
ashleymills 0:00174d07d068 242 // set client method
ashleymills 0:00174d07d068 243
ashleymills 0:00174d07d068 244 // TLS
ashleymills 0:00174d07d068 245 //CYASSL_CTX* ctx = CyaSSL_CTX_new(CyaSSLv23_client_method());
ashleymills 0:00174d07d068 246
ashleymills 0:00174d07d068 247 // DTLS
ashleymills 0:00174d07d068 248 CYASSL_METHOD* method = CyaDTLSv1_2_client_method();
ashleymills 0:00174d07d068 249 if(method == NULL) {
ashleymills 0:00174d07d068 250 // unable to get method
ashleymills 0:00174d07d068 251 }
ashleymills 0:00174d07d068 252 CYASSL_CTX* ctx;
ashleymills 0:00174d07d068 253 ctx = CyaSSL_CTX_new(method);
ashleymills 0:00174d07d068 254 if(ctx == NULL){
ashleymills 0:00174d07d068 255 DBG("CyaSSL_CTX_new error.\n");
ashleymills 0:00174d07d068 256 exit(EXIT_FAILURE);
ashleymills 0:00174d07d068 257 }
ashleymills 0:00174d07d068 258
ashleymills 0:00174d07d068 259 DBG("Setup SSL context");
ashleymills 0:00174d07d068 260
ashleymills 0:00174d07d068 261
ashleymills 0:00174d07d068 262
ashleymills 0:00174d07d068 263
ashleymills 0:00174d07d068 264 // use pre-shared keys
ashleymills 0:00174d07d068 265 //CyaSSL_CTX_set_psk_client_callback(ctx,my_psk_client_cb);
ashleymills 0:00174d07d068 266 /*
ashleymills 0:00174d07d068 267 if(CyaSSL_CTX_load_verify_buffer(ctx, serverCert, strlen((const char*)serverCert),SSL_FILETYPE_PEM)==0) {
ashleymills 0:00174d07d068 268 DBG("loaded server cert OK");
ashleymills 0:00174d07d068 269 }*/
ashleymills 0:00174d07d068 270
ashleymills 0:00174d07d068 271 // load certificates for CA and us
ashleymills 0:00174d07d068 272 // load CA cert
ashleymills 0:00174d07d068 273 ret = CyaSSL_CTX_load_verify_buffer(ctx,rootCertificate, rootCertificateLength,SSL_FILETYPE_ASN1);
ashleymills 0:00174d07d068 274 // load device cert
ashleymills 0:00174d07d068 275 ret = CyaSSL_CTX_use_certificate_buffer(ctx, deviceCertificate, deviceCertificateLength, SSL_FILETYPE_ASN1);
ashleymills 0:00174d07d068 276 // load device private key
ashleymills 0:00174d07d068 277 ret = CyaSSL_CTX_use_PrivateKey_buffer(ctx, devicePrivateKey, devicePrivateKeyLength, SSL_FILETYPE_ASN1);
ashleymills 0:00174d07d068 278
ashleymills 0:00174d07d068 279 int sockfd = NULL;
ashleymills 0:00174d07d068 280 if(!connectToSocketUDP("192.168.1.99", 11111, &sockfd)) {
ashleymills 0:00174d07d068 281 DBG("Error connecting to socket");
ashleymills 0:00174d07d068 282 }
ashleymills 0:00174d07d068 283
ashleymills 0:00174d07d068 284 /*
ashleymills 0:00174d07d068 285 // connect to SSL enabled webserver
ashleymills 0:00174d07d068 286 int sockfd = NULL;
ashleymills 0:00174d07d068 287 if(!connectToSocket("95.47.118.120", 11111, &sockfd)) {
ashleymills 0:00174d07d068 288 DBG("Error connecting to socket");
ashleymills 0:00174d07d068 289 }
ashleymills 0:00174d07d068 290 DBG("Connected to non-SSL socket");
ashleymills 0:00174d07d068 291 */
ashleymills 0:00174d07d068 292
ashleymills 0:00174d07d068 293 // hook into SSL
ashleymills 0:00174d07d068 294 // Create CYASSL object
ashleymills 0:00174d07d068 295 CYASSL* ssl;
ashleymills 0:00174d07d068 296 ssl = CyaSSL_new(ctx);
ashleymills 0:00174d07d068 297 if(ssl == NULL) {
ashleymills 0:00174d07d068 298 DBG("CyaSSL_new error.");
ashleymills 0:00174d07d068 299 exit(EXIT_FAILURE);
ashleymills 0:00174d07d068 300 }
ashleymills 0:00174d07d068 301 DBG("CyaSSL_new OK");
ashleymills 0:00174d07d068 302
ashleymills 0:00174d07d068 303 // setup callbacks for handshake failure
ashleymills 0:00174d07d068 304 /*
ashleymills 0:00174d07d068 305 Timeval timeout;
ashleymills 0:00174d07d068 306 timeout.tv_sec = 5;
ashleymills 0:00174d07d068 307 timeout.tv_usec = 0;
ashleymills 0:00174d07d068 308 ret = CyaSSL_connect_ex(ssl, handshakeCallback, timeoutCallback, timeout);
ashleymills 0:00174d07d068 309 */
ashleymills 0:00174d07d068 310
ashleymills 0:00174d07d068 311 // attach to socket
ashleymills 0:00174d07d068 312 DBG("Attaching CyaSSL to socket");
ashleymills 0:00174d07d068 313 CyaSSL_set_fd(ssl, sockfd);
ashleymills 0:00174d07d068 314 DBG("Attached CyaSSL to socket");
ashleymills 0:00174d07d068 315
ashleymills 0:00174d07d068 316 // DTLS stuff
ashleymills 0:00174d07d068 317 ret = CyaSSL_dtls_set_peer(ssl, &serverAddress, sizeof(serverAddress));
ashleymills 0:00174d07d068 318 if(ret != SSL_SUCCESS) {
ashleymills 0:00174d07d068 319 // failed to set DTLS peer
ashleymills 0:00174d07d068 320 DBG("Failed to set DTLS peer");
ashleymills 0:00174d07d068 321 }
ashleymills 0:00174d07d068 322
ashleymills 0:00174d07d068 323 ret = CyaSSL_dtls(ssl);
ashleymills 0:00174d07d068 324 if(ret) {
ashleymills 0:00174d07d068 325 // SSL session has been configured to use DTLS
ashleymills 0:00174d07d068 326 DBG("DTLS configured");
ashleymills 0:00174d07d068 327 } else {
ashleymills 0:00174d07d068 328 DBG("DTLS not configured");
ashleymills 0:00174d07d068 329 }
ashleymills 0:00174d07d068 330
ashleymills 0:00174d07d068 331
ashleymills 0:00174d07d068 332
ashleymills 0:00174d07d068 333 DBG("Issuing CyaSSL_connect");
ashleymills 0:00174d07d068 334 int result = CyaSSL_connect(ssl);
ashleymills 0:00174d07d068 335 if(result!=SSL_SUCCESS) {
ashleymills 0:00174d07d068 336 DBG("CyaSSL_connect failed");
ashleymills 0:00174d07d068 337 printError(ssl,result);
ashleymills 0:00174d07d068 338 }
ashleymills 0:00174d07d068 339 DBG("CyaSSL_connect OK");
ashleymills 0:00174d07d068 340
ashleymills 0:00174d07d068 341 result = CyaSSL_write(ssl,"onion",5);
ashleymills 0:00174d07d068 342 DBG("Wrote %d things",result);
ashleymills 0:00174d07d068 343 if(result<0) {
ashleymills 0:00174d07d068 344 printError(ssl,result);
ashleymills 0:00174d07d068 345 }
ashleymills 0:00174d07d068 346
ashleymills 0:00174d07d068 347 char buffer[200];
ashleymills 0:00174d07d068 348 int d =0;
ashleymills 0:00174d07d068 349 if((d=CyaSSL_read(ssl, &buffer, 200))>0) {
ashleymills 0:00174d07d068 350 DBG("Received %d bytes: %s",d,buffer);
ashleymills 0:00174d07d068 351 }
ashleymills 0:00174d07d068 352
ashleymills 0:00174d07d068 353 // clean up
ashleymills 0:00174d07d068 354 CyaSSL_CTX_free(ctx);
ashleymills 0:00174d07d068 355 CyaSSL_Cleanup();
ashleymills 0:00174d07d068 356
ashleymills 0:00174d07d068 357 }