>> µTLS - DEFINING LIGHTWEIGHT SECURITY FOR IoT (PART 4)
You can never appreciate how valuable resources are until they get out of
your reach!
So far, the
µTLS (micro TLS)
project is coming along well - with promising results that it is definitely
feasible to secure the most resource constrained devices out there. It is
my hope that this entry cements that reality in your mind and you see a
commercial viability for such a solution. By now you should understand
the basic architecture and protocol of the solution - let's dig a little
deeper now.
In my earlier entry; I provided the basics for the µTLS (micro TLS)
server and two protocol implementations - namely, none and
rot13. I left it up to the reader to figure out how to modify the
client that was provided in order to make it work with the rot13
module - did you even attempt it?
What exactly is required to upgrade our client from none to
rot13?
Well; first of all, we need some functions that can perform rot13
on a buffer - taking into consideration that memory is a valuable resource.
You can find a number of implementations on the internet, but this is what
I eventually ended up using in my example.
char rot13_single(char c)
{
if ((c >= 'a') && (c <= 'z')) return (((c-'a') + 13) % 26)+'a';
else if ((c >= 'A') && (c <= 'Z')) return (((c-'A') + 13) % 26)+'A';
else return c;
}
void rot13(char *src, int len)
{
for (int i=0;i<len;i++) src[i] = rot13_single(src[i]);
}
The next step is to change the communication protocols for the POST
and PUT requests:
@@ -405,7 +424,7 @@
"{" \
"\"protocol\":\"none\"," \
"\"response\":\"none\"," \
- "\"protocol_sub\":\"none\"" \
+ "\"protocol_sub\":\"rot13\"" \
"}" \
"}";
@@ -669,8 +688,8 @@
"\"," \
"\"security\":" \
"{" \
- "\"protocol\":\"none\"," \
- "\"response\":\"none\"" \
+ "\"protocol\":\"rot13\"," \
+ "\"response\":\"rot13\"" \
"}," \
"\"data\":" \
"{" \
We want to change the communications protocol such that after the initial
request; all communications should be performed using the rot13
substitution cipher. There are no configuration parameters of rot13 -
so we only need to makes changes in the PUT handler.
@@ -700,6 +719,10 @@
int msg_len = strlen(msg);
// --------------------------------------------------------------------
+ // the must encode the message using rot13
+ rot13(msg, strlen(msg));
+
+ // we need to
#ifdef ENABLE_DEBUG
Serial.println(F(":: attempting connection to server"));
First we must encode the message we are sending over to the server, as
shown above.
@@ -855,6 +878,9 @@
#endif
#endif
+ // the message has been encoded using rot13
+ rot13((char *)b, b_len);
+
#ifdef ENABLE_DEBUG
// display the buffer
Serial.print(F("** decoded form: "));
Finally; when we receive a message from the server in the data.buffer
key; we just need to decode the buffer that we allocated and copies the
base64 decoded message into. Before we discard the memory that was allocated
the client should interpret the message of course.
With these changes; you should now have a working rot13 client with
the µTLS (microTLS) server.
Sketch uses 13,738 bytes (42%) of program storage space.
Global variables use 443 bytes (21%) of dynamic memory,
leaving 1,605 bytes for local variables. Maximum is 2,048 bytes.
In comparison to the none client - there are no changes in the
memory foot print as we didn't use any additional variables but there was a
small increase in the program storage due to the addition code for performing
the rot13 operations - this was expected outcome of course.
GETTING SERIOUS: RC4
RC4
(Rivest Cipher 4) is a simple stream cipher. while remarkable for
its simplicity and speed in software, it has been know to have some
vulnerabilities; but these can be dealt with by throwing away a number
of initial output bytes in the stream - something we can handle in our
protocol.
The design of the client we posted earlier had some minor flaws; mainly
in regards to how it would deal with accepting a large buffer in the
data.buffer key that is exchanged from the server. It was by
design to provide a proof-of-concept that would be easy to follow, for
my readers.
Some tricks are needed get it to remain stable.
Unfortunately; I currently consider these "trade secrets" - I will not
be posting those changes for the public freely at this point. I truly
believe there is some commercial viability in µTLS (micro TLS) -
with that said, do reach out to me if you want to know more or seek a
collaboration.
Now - back to RC4 - it took quite a bit of work - but we have a working
RC4 implementation:
:: attempting connection to server
** connected
-- 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: 118
{
"guid": "ffa90e64-f3e2-4697-b98c-e3c13d1b2362",
"security": {
"protocol":"none",
"response":"none",
"protocol_sub":"rc4"
}
}
-- response:
HTTP/1.1 200 OK
Date: Thu, 15 Dec 2016 10:58:06 GMT
Server: Apache
Content-Length: 560
Connection: close
Content-Type: application/json
{
"session": "e91f5584152639c72d5358a05f9cd88758527740d09bb",
** found session: e91f5584152639c72d5358a05f9cd88758527740d09bb
"security": {
"response": "none",
"protocol": "rc4"
},
"data": {
"ts": "1481886117",
** found ts: 1481886117
"buffer": "AAuEtUUu2zqq1fY22ZivTTlJKOOeAY441FBzzq3kPP/eRSS02y
66ehaTTeHMss7ME33FNDZZczwnnTkXFFf8RCCpIc99jzCeeZc6
AA+VmLLbv488FKliiRZvEEtDlbbU7r99NS9kkBWvMMF9JHH55W
SSz9CXXCb055qJsjjWcqeebuJwwcpFXX65yaauj1uuEt+BB/Rd
EEiT8xxBJxJJeQ3tth3eAA/n1++nW0aacA2mm1YZqqiwbDDI4H
GGDciTTrxAjj9IyIIQPcMM7x9yyKxK774cZEEjyzFF61miiY2p
FFRWCZZbDNbbevmee0ChEEoKwVVFkE88bS+UULXnNNaDJss93Y
BBKsG++7tk99wLkrrP5qggq3SyyKmWGGMZfllzfCSSzr/55NcA
mm+0hXXD0lssH4j44CxLSSALAqqQ=="
** found buffer: *streamed*
** decoded form: 02 E1 2D 52 ED B3 AB 57 D8 D9 98 AF 4E 52 4A 39
E0 18 E3 51 41 CE AD E4 3F F7 91 4B 4D B2 E9 E8
5A 4D E1 CC B3 B3 04 DC 53 43 65 CC F0 9D 39 17
15 FF 11 0A 92 1C F6 3C C2 79 97 3A 03 E5 66 2D
BB F8 F0 52 A5 89 16 6F 12 D0 E5 6D 4E EB F4 D4
BD 90 15 AF 30 5F 49 1F 9E 56 4B 3F 42 5C 26 F4
E6 A2 6C 8D 67 2A 79 BB 89 C1 CA 45 5F AE 72 6A
E8 F5 B8 4B 7E 07 F4 5D 12 24 FC C4 12 71 25 E4
37 B6 1D DE 03 F9 F5 FA 75 B4 69 C0 36 9B 56 19
AA 2C 1B 0C 8E 07 18 37 22 4E BC 40 8F D2 32 21
03 DC 33 BC 7D C8 AC 4A EF 87 19 12 3C B3 17 AD
66 89 8D A9 15 15 82 65 B0 CD 6D EB E6 7B 40 A1
12 82 B0 54 59 04 F1 B4 BE 50 B5 E7 35 A0 C9 B3
DD D8 04 AB 06 FB BB 64 F7 02 E4 AC FE 6A 82 AD
D2 C8 A9 96 18 C6 5F 97 37 C2 4B 3A FF E4 D7 00
9B ED 21 5C 3D 25 B0 7E 23 E0 2C 4B 48 02 C0 A9
}
}
Once again; for the sake of readability I manually edited the data being
sent and the received data (highlighted in bold) instead of it being on
a single line. What you can see from this initial request is the exchange
of the 256-byte key that the RC4 algorithm should use for all
future communication.
Our goal is now to send an encrypted message and receive an encrypted
response from the server.
:: 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: 118
{
"session": "e91f5584152639c72d5358a05f9cd88758527740d09bb",
"security": {
"protocol":"rc4",
"response":"rc4"
},
"data": {
"params":"2073",
"buffer":"UQLDWadAJPtWkQmMe8lYwkGzhfuPrEFXnOv8kZJxhQ=="
}
}
-- response:
HTTP/1.1 200 OK
Date: Fri, 16 Dec 2016 11:02:02 GMT
Server: Apache
Content-Length: 293
Connection: close
Content-Type: application/json
sending a message over microTLS
{
"session": "e91f5584152639c72d5358a05f9cd88758527740d09bb",
"security": {
"response": "rc4",
"protocol": "rc4"
},
"data": {
"ts": "1481886124",
** found ts: 1481886124
"params": "2082",
** found params: 2082
"buffer": "22QuebbMMZ11UXhnnuOPrrEA="
** found buffer: *streamed*
** decoded form: D9 0B 9E 6C C3 19 D5 45 E1 9E E3 8F AC 40
** ASCII form: ...l...E.....@
** decrypted: 68 6F 77 64 79 20 70 61 72 74 6E 65 72 21
** ASCII form: howdy partner!
}
}
Without going into the specific details; we can argue that since we
were able to see the message in the response and decrypt the message
from the server without it being garbage - everything works! In order
to resolve the security risk of using RC4, we have utilized
our data.params key to have some form of dynamic throw-away
counter that we should use when using RC4.
So; how does the RC4 client match up compared to the others?
Sketch uses 15,246 bytes (47%) of program storage space.
Global variables use 715 bytes (34%) of dynamic memory,
leaving 1,333 bytes for local variables. Maximum is 2,048 bytes.
We have seen an increase of around 1.5kb for the RC4 implementation
and 300 bytes additional memory; which accounts for the 256-byte key exchanged
when the session is initialized and other variables used as part of our
secure random number
generator.
While we could argue that the on-going exchange of information between the
client and server is secure - until we resolve the initial exchange of the
256-byte RC4 key; it isn't secure for commercial use. We still have
plenty of memory available however to implement a secure exchange.