Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[tinydtls-dev] Secure Version of dtls_prng()

Hello all,

Attached you find the code of a secure implementation of dtls_prng().

 

Notes:

 

1.)    Not yet tested, but I am quite confident that the concept is Cryptographically Strong. Comments are of course welcome.

2.)    Still using 3DES(). I will supply the AES variant as soon as I have time for that.

3.)    If you find a problem, please report it. I can handle criticism J

 

Kind regards

 

Frank Gerlach

 

 

 

 

#include "flash_nava.h"

#include "des.h"

#include "secureRandomNumber.h"

#include "flash_names.h"

#include <memory.h>

 

 

#define PRNG_COUNTER_INCREMENT 1024

 

/* Load the secret physical randomness value from persistent storage.

*

 * This function is hardware-dependent and must be provided by the

* software engineer using this library */

bool loadPhysicalRandomness(BYTE randomness[24])

{

    good_c_buffer buffer;

    initGoodBuf(&buffer,64);

    bool ret = false;

    if( readFromFlash(FN_PHYS_RANDOMNESS_SECRET,&buffer,true) )

    {       

        if( buffer.valid >= (24*2))

        {

            good_c_buffer bufOut;

            initGoodBuf(&bufOut,24);

            if( convertHexToBinary(&buffer,&bufOut) && (bufOut.valid >= 24))

            {

                uint8_t i;

                for(i=0; i < 24;i++)

                {

                    randomness[i] = bufOut.rawBuf[i];

                }

                bool ret = true;          

            }

            freeGoodBuf(&bufOut);

        }

    }

    freeGoodBuf(&buffer);

    return ret;

}

 

/* Load the PRNG Counter and increment it. Store the new counter state

* to persistent storage.

*

 * This function is hardware-dependent and must be provided by the

* software engineer using this library */

bool loadCounterAndIncrement(uint64_t* counter,uint32_t increment)

{

    good_c_buffer buffer;

    initGoodBuf(&buffer,64);

    bool ret = false;

    if( readFromFlash(FN_PRNG_CTR,&buffer,true) )

    {       

         if( convertHexToUI64(&buffer,counter) )

         {

            uint64_t newVal = (*counter) + PRNG_COUNTER_INCREMENT;

            if( convertUI64ToStr(newVal,&buffer) )

            {

                terminateString(&buffer);

                if( flash_key_value_set(FN_PRNG_CTR,buffer.rawBuf) )

                {

                   ret = true;       

                }                

            }           

         }        

    }

    freeGoodBuf(&buffer);

    return ret;

}

 

bool     g_prngIsInitialized;

uint64_t g_prngCounter;

uint64_t g_prngCounterNextLoad;

BYTE     g_three_schedule[3][16][6];

BYTE     g_desKEY[24];

 

 

 

 

/************************************************************************************************

* The following mechanism provides Cryptographically Strong Pseudo-Random Numbers,

* even on very limited devices.

 *

 * The Basic Concept is very simple:

*

 * 1.) Have 128 (or 256) bits of physical randomness PHRANDOM_SECRET in persistent memory.

* 2.) Have a 64 bit counter CTR in persistent memory.

* 3.) Have a symmetric cipher Ciphertext = SCipher(Key,Plaintext). E.g. 3DES.

* 4.) To obtain a word of pseudo-random bits:

*        4.1 calculate RandomData = SCipher(PHRANDOM_SECRET,CTR)

*        4.2 increment CTR

*        4.3 persist CTR to storage

*

 *

 *

 * Arguably, it could also replace the /dev/random system of Linux and be a better alternative

* to that, because the various sources of "randomness" in /dev/random are not properly

* understood.

*

 * Bandwidth of the system is only limited by computational requirements of the symmetric cipher.

* Parallelization can be easily achieved and can allow for unlimited scalability.

*

 * The current implementation is made for the ESP8266 device, but can be easily adapted to

 * other information systems - either small or large.

*

 *

 * Note 1: It does of course "not hurt" to collect (somewhat) random data and to XOR-mix it into the

*         secure physical random number. A hash function could be used to the same end,

*         e.g. Davies-Meyer-3DES Hash.

*         This is NOT STRICTLY NECESSARY, though. The only requirement is to keep the random

*         128 bit number secure. That might include eventual deletion/replacement.

*

 * Note 2: Other symmetric Block ciphers such as GOST 28147-89, Chiasmus, AES or Blowfish

 *         could be used instead 3DES. Of course, all ciphers must be considered "cryptographically strong",

*         which is a quality that will change over the span of several decades.

 *

 * Note 3: Hardware which has a limited number of write cycles (typically some type of EEPROM/Flash memory)

*         should keep track of the number of write cycles for each Flash page and make

 *         sure only "expected good" Flash Memory pages are being used for the storage of

 *         CTR and PHRANDOM_SECRET. Typically, a Flash page can only be correctly written 1000 to 10000

*         times.

 *        

 */

bool getSecureRandomness(uint64_t* secureRandomNumber)

{

    if( g_prngIsInitialized == false )

    {   

        if( !loadPhysicalRandomness(g_desKEY) )

        {

            return false;

        }

        three_des_key_setup(g_desKEY, g_three_schedule, DES_ENCRYPT);

        g_prngIsInitialized = true;

    }

    if( (g_prngCounter == 0) || (g_prngCounter == g_prngCounterNextLoad)  )

    {

     

        if( loadCounterAndIncrement(&g_prngCounter,PRNG_COUNTER_INCREMENT) )

        {

            g_prngCounterNextLoad = g_prngCounter + PRNG_COUNTER_INCREMENT;

        }

        else

        {

            return false;

        }

    }

   

    three_des_crypt((BYTE*)&g_prngCounter,(BYTE*)secureRandomNumber,(const BYTE (*)[16][6])g_three_schedule);

    g_prngCounter++;

}

 

int dtls_prng(unsigned char *buf, size_t len)

{

   

    uint16_t n = len >> 3;

    bool rest = len & 0x7;

  

    uint64_t cryptoStrongRandom;

    uint8_t i;

    for(i=0;i < n ;i++)

    {

       

        getSecureRandomness(&cryptoStrongRandom);

        memcpy(buf,&cryptoStrongRandom,8);

        buf += 8;

    }

    if( rest )

    {

        getSecureRandomness(&cryptoStrongRandom);

        memcpy(buf,&cryptoStrongRandom,rest);

    }

    return 1;

}

 

 

 

Frank Gerlach

Senior Software Engineer

 

Office: +375 17 389 0100 x 23178   Cell: +375 29 877 4976    Email: frank_gerlach@xxxxxxxx

Minsk, Belarus (GMT+3)   epam.com

 

CONFIDENTIALITY CAUTION AND DISCLAIMER
This message is intended only for the use of the individual(s) or entity(ies) to which it is addressed and contains information that is legally privileged and confidential. If you are not the intended recipient, or the person responsible for delivering the message to the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. All unintended recipients are obliged to delete this message and destroy any printed copies.

 


Back to the top