>> µTLS - DEFINING LIGHTWEIGHT SECURITY FOR IoT (PART 7)
Celebrations are in order - I reached a critical milestone with µTLS
(micro TLS)!
I am proud to announce that today we hit a massive milestone in the
µTLS (micro TLS)
project - we can confirm that an Arduino UNO is capable of implementing
a secure communication protocol. Using ECC-163, the client gains the trust
of the server and exchanges secret keys to have ongoing communication using
AES-128. The final pieces are almost in place to make this a product.
I am confident that my Arduino UNO is now sufficiently secure regarding
data transmission.
Here is an excerpt from the console logging, showing each step of the
communication.
:: attempting connection to server
** connected
-- request:
GET /xxx/index.php HTTP/1.1
Host: xxx.xxxxxxxx.xxx
User-Agent: Arduino/1.0
Connection: close
-- response:
HTTP/1.1 200 OK
Date: Wed, 21 Dec 2016 13:52:29 GMT
Server: Apache
Content-Length: 104
Connection: close
Content-Type: application/json
{
"data": {
"ts": "1482328349",
** found ts: 1482328349
"token": "DWMNDBKWIVBXGJSVMJXPZZJXXHCBPMIT"
** found token: DWMNDBKWIVBXGJSVMJXPZZJXXHCBPMIT
}
}
The first step is to have the server gain trust from the client. This is
done by generating a unique token using a HTTP GET and asking the
client to verify who they claim to be. The client now has the responsibility
to encrypt the token and provide on session creation. The token can only
be used once; and has a TTL (time to live) attribute associated to it -
meaning cloning a client wont work.
-- request:
POST /xxx/index.php HTTP/1.1
Host: xxx.xxxxxxxx.xxx
User-Agent: Arduino/1.0
Connection: close
Content-type: application/x-www-form-urlencoded
Content-Length: 259
{
"guid": "ffa90e64-f3e2-4697-b98c-e3c13d1b2362",
"security": {
"protocol": "ecc-163",
"response": "ecc-163",
"protocol_sub":"aes-128",
"buffer": "BwAAAMTXTDaJDS53mLWGDvRtnqxYw5HMAQAAADeRVuPSTzotNHKf2
m4X2ItANUNBGtO3CRTsglpTJS3UMl/ERgj34yhe0tQQNcZxTF2sVo
adB0PmpZHF5A=="
}
}
-- response:
HTTP/1.1 200 OK
Date: Wed, 21 Dec 2016 09:18:29 GMT
Server: Apache
Content-Length: 319
Connection: close
Content-Type: application/json
{
"session": "e91f5584152639c72d5358a05f9cd887585a48e9385a4",
** found session: e91f5584152639c72d5358a05f9cd887585a48e9385a4
"security": {
"response": "ecc-163",
"protocol": "aes-128"
},
"data": {
"ts": "1482311913",
** found ts: 1482311913
"buffer": "AAgAAAAOO6ffLBshhoDaJJ2ZxssG6xnnthyuugB4AAQAAAABcy
TTH1Hff8Qrjj05s++Fjk55yEittp/0IIKh1QQroN44JHJyyKqM
BBjVyCCumHssn/raaA/A"
** found buffer: *streamed*
}
}
** decoded len: 72
** decoded form: 02 00 00 00 E3 BA 7C B0 6C 86 80 DA 27 66 71 B0
6E B1 9E D8 72 BA 00 78 01 00 00 00 17 32 4C 7D
47 7F C4 2B 8F 4E 6C F8 58 E4 E7 21 22 B6 9F F4
20 A8 75 42 BA 0D E0 91 C9 C8 AA 8C 06 35 72 0A
E9 87 B2 7F EB 68 0F C0
** ASCII form: ......|.l...'fq.n...r..x.....2L}G..+.Nl.X..!"..
. .uB.........5r......h..
** decrypted: 7C 42 E7 A3 30 97 F0 AD 85 B4 71 B9 E1 63 78 73
** ASCII form: |B..0.....q..cxs
The client informs the server it will use the ECC-163 protocol
and then encrypts the token received using the public key of the server -
the encrypted value is placed in the security.buffer key. The
server uses its private key to decrypt the message and verify if the
token exists and if it is still valid. The token is removed from the
server; otherwise a 401 (unauthorized) response is returned.
The server also generates a key for the aes-128 algorithm that
the client wishes to communicate with - it then encrypts that using
ECC-163 using the public keys of the client. In theory; only
the client will be able to decrypt the packet using the private key
compiled into it. On success; the communication will switch over
to a more session friendly and less overhead aes-128.
:: attempting connection to server
** connected
-- request:
PUT /xxx/index.php HTTP/1.1
Host: xxx.xxxxxxxx.xxx
User-Agent: Arduino/1.0
Connection: close
Content-type: application/x-www-form-urlencoded
Content-Length: 199
{
"session": "e91f5584152639c72d5358a05f9cd887585a48e9385a4",
"security": {
"protocol": "aes-128",
"response": "aes-128"
},
"data": {
"buffer": "Ohd67wk2tuV0UEoUCFhPe7Mnt3KjeIrWDJWgOwBRQbXfrfwqIcT6fB
CJcawE2WCX"
}
}
-- response:
HTTP/1.1 200 OK
Date: Wed, 21 Dec 2016 09:19:10 GMT
Server: Apache
Content-Length: 299
Connection: close
Content-Type: application/json
sending a message over microTLS
{
"session": "e91f5584152639c72d5358a05f9cd887585a48e9385a4",
"security": {
"response": "aes-128",
"protocol": "aes-128"
},
"data": {
"ts": "1482311952",
** found ts: 1482311952
"buffer": "RRG+q8883ZggXVCIIZrG77Bw4MMVZH++dQ088OFs11XjkBB50w
nnLg="
** found buffer: *streamed*
}
}
** decoded len: 32
** decoded form: 44 6F AA F3 CD D9 81 75 42 21 9A C6 EC 1C 38 31
56 47 F9 D4 34 F0 E1 6C D5 78 E4 07 9D 30 9C B8
** ASCII form: Do.....uB!....81VG..4..l.x...0..
** decrypted: 68 6F 77 64 79 20 70 61 72 74 6E 65 72 21
** ASCII form: howdy partner!
We can see the message sent by the client was received ok and the message
sent from the server "howdy partner!" was decrypted successfully on the
client. All subsequent communications will be performed using the
aes-128 until the client decided it is time to create a new
session; in which case it will re-authenticate with the server like it
did on first connection.
So; how big is the application now with ECC-163 and aes-128?
Sketch uses 31,168 bytes (96%) of program storage space.
Global variables use 1,012 bytes (49%) of dynamic memory,
leaving 1,036 bytes for local variables. Maximum is 2,048 bytes.
What? - do not worry, thats with full debugging and nice pretty output
to verify all is ok.
Sketch uses 24,130 bytes (74%) of program storage space.
Global variables use 960 bytes (46%) of dynamic memory,
leaving 1,088 bytes for local variables. Maximum is 2,048 bytes.
That's more like it - the Arduno UNO has plenty of space left to
read sensors and issue commands.
I was almost spot on suggesting that there would be around 8Kb of
program space - the great news is that with a slight restructuring of
the client I was able to leave just over 1Kb of free dynamic memory!
In addition, the client has a 512 byte scratch area that can be utilized
to share data between application states - in fact, the maximum dynamic
memory used was just over 600 bytes.
The only thing left to do now is integrate some message authentication;
to make sure that the Arduino UNO doesn't launch nuclear missiles in the
even the decryption of the messages exchanged didn't go astray or was
tampered with by a third party (MITM attack) in any way. In fact; most
algorithms one integrated - but it isn't difficult ot add a checksum or
hash for verification.