Aaron Ardiri
[Valid RSS] RSS/XML feed
198 entries available (show all)

 

Internet of Things (IoT)
   

PLEASE TAKE A MOMENT TO FOLLOW MY NEW VENTURE:
 
RIoT Secure AB
 
ALL SECURITY RELATED TOPICS ON IoT wILL BE POSTED THERE


2016-12-12
>> µTLS - DEFINING LIGHTWEIGHT SECURITY FOR IoT (PART 1)

I have been meaning to come back to this for quite some time - enough is enough.

Since I started this blog, security has been one hell of a topic that I have covered within the field of Internet of Things (IoT) - such as the general mass fear complete to actually taking the time to test the feasibility of security on micro-controllers. It is time we did something about it; more than just talking about it - but actually building a protocol and implementing it. I am proud to introduce µTLS!

µTLS (micro Transport Layer Security) is a protocol that aims to provide privacy and data integrity between two communicating computer applications, with limited CPU power and memory resources, specifically for use within the Internet of Things (IoT) field. It is designed to be open and flexible; to suit the demands of the various micro-controllers that are in use.

The µTLS protocol is implemented over non-encrypted HTTP traffic and is designed under the pretense that unless anyone listening in on the conversation speaks the same language - then the contents of the information exchanged remains private and as such secure. It is no different than two people talking Mandarin amongst a group of English who do not understand Mandarin.

COMMUNICATION HANDSHAKE
The handshake phase occurs when the client device establishes communication with the server with the desire to exchange information; either for the purpose of uploading sensory data or requesting operational instructions - the terms of communication must be defined.

A session creation request may look as follows:

    POST /index.php
    {
      "guid": "ffa90e64-f3e2-4697-b98c-e3c13d1b2362",
      "security": {
        "protocol": "none",
        "response": "none",
        "protocol_sub": "none"
      },
      "info": {
        "name": "Weather Station",
        "company": "RIot International Pty Ltd",
        "build": "2016-12-01",
        "version": "1.0"
      } 
    }
    

The request is quite simple, requiring the guid (identifier) and security keys as a bare minimum - they are used to determine if the server can trust the client or not. The info key can be optionally provided; depending on the requirements of the application. In this case; the security.protocol is set to none and that the client expects the response to be unencrypted for further communications as defined in the security.response and security.protocol_sub keys.

On successful validation; the server responds with information on how to make subsequent requests to allow the exchange of information with the client. An example of such a response is:

    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "protocol": "none",
        "response": "none"
      }
      "data": {
        "ts": "1481544512"
      }
    }
    

A unique session key is provided that the client can use to avoid having to re-validate itself with the server every time. The security definition has two components; the protocol to use in the response and how the client should continue talking to the server.

These are defined in the security.response and security.protocol keys - in the example these are defined as none. Optionally, the data key can contain information that may be of use to the client (such as sending the server timestamp to sync time locally on the client).

The client can then make subsequent requests:

    PUT /index.php
    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "protocol": "none",
        "response": "none"
      }
      "data": {
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz" 
      }
    }
    

The data.buffer will then contain the HEX encoded buffer that the client wishes to send to the server for processing. Utilizing the security method defined in security.protocol the server can then process the information received and can respond to the client appropriately:

    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "protocol": "none",
        "response": "none"
      },
      "data": {
        "ts": "1481544610",
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz" 
      }
    }
    

In this example; there is absolutely no security in the communication.

In a production environment; this would not be a sensible setup to use - as the data would be sent without any protection and the server will not be capable of validating if the client is who they claim to be. The next step would be to extend the protocol to define a level of security.

COMMUNICATION SECURITY
Within the initial communication between the client and server - the client defines the security key - it is vital as it defines how the client and server should exchange information in addition to allow for some low-level checking to verify if the client is actually who they say they are.

The security.protocol key defines the sub-protocol to be used as part of the validation; and the security.buffer key contains a HEX encoded buffer of information the server can use to verify the legitimacy of the client. On failure, the server rejects communication.

The exact nature of how the client and server perform this validation is completely open - the only requirement is that whatever input data required to generate the security.buffer based on the sub-protocol security.protocol must be provided within the request.

As an example; here is a much more secure configuration:

For example, consider the following security definition.

      "security": {
        "protocol": "rsa-1024",
        "response": "rsa-1024",
        "protocol_sub": "aes-128",
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz"
      }
    

In this case the client has sufficient resources to perform a 1024 bit private-key RSA encryption operation locally. The client has also indicated that it can handle 1024 bit RSA of the server and the AES-128 protocol. The server could now use the guid key to find the corresponding public-key of the client and then decrypt the data in security.buffer - if it is a successful request then the result will match a value that only the client and server is aware of.

On successful validation; the server will respond with:

    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "response": "rsa-1024",
        "protocol": "aes-128"
      }
      "data": {
        "ts": "1481544512",
        "params": "abcdef",
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz"
      }
    }
    

Similar to the insecure response; a unique session key is provided to avoid having to re-validate itself with the server every time, in addition to the security.response and security.protocol keys - defining how to handle the response and make further communication. The client has defined the security protocols it can handle, so the server can now respond appropriately.

In this example; the client requests to communicate using aes-128. However; in order to initialize the protocol; it needs to send over a number of base values - in this case, the buffer to initialize AES-128 with. rsa-1024 has been requested for the response of the request - the data will then be encrypted using the private key of the server and placed in the data.buffer key.

If some parameters are required to give context on how to process the data.buffer structure once it is decoded from a HEX string; these parameters will be passed in unencrypted form via the data.params key - such as syncing indexes between server and client.

The client now has all the information it needs to process the result - and extract the information stored in the data.buffer key. It can as a result use the 1024-bit RSA algorithm and decrypt it based on the public key of the server it has compiled into it. The contents would then be used to initialize the secondary protocol (AES-128) defined.

A subsequent request would look like:

    PUT /index.php
    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "protocol": "aes-128",
        "response": "aes-128"
      }
      "data": {
        "params": "abcdef",
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz" 
      }
    }
    

In which the server will respond with:

    {
      "session": "e91f5584152639c72d5358a05f9cd887584edaf9b6f06",
      "security": {
        "response": "aes-128",
        "protocol": "aes-128"
      },
      "data": {
        "ts": "1481544610",
        "params": "abcdef",
        "buffer": "xxyyzzxxyyzzxxyyzz....xxyyzzxxyyzzxxyyzz" 
      }
    }
    

Using a combination like rsa-1024/aes-128 is in line with the security of some existing HTTPS environments; however, the manner in which keys are exchanged and validated are less open - as they keys need to be compiled into the client and server environments accordingly. In essence; we have simply removed the overhead contained with TLS - namely having to deal with raw X.509 certificates, certificate authorities and the like.

So; what's next for µTLS?

First things first; I will build some examples based on the design specified here. Putting the idea to the test should be able to rule out if the protocol is feasible for use in real-world projects. I have quite a lot of code optimized for micro-controllers that would be usable with minimal modification.


 

advertisement (self plug):
need assistance in an IoT project? contact us for a free consultation.

 



µTLS - defining lightweight security for IoT (part 2)
 
Anatomy of a parallel application (MPI basics)

DISCLAIMER:
All content provided on this blog is for informational purposes only.
All comments are generated by users and moderated for inappropriateness periodically.
The owner will not be liable for any losses, injuries, or damages from the display or use of this information.