152 lines
4.3 KiB
C
152 lines
4.3 KiB
C
#include "echo_random.h"
|
|
#include "mbedtls/md_internal.h"
|
|
#include "mbedtls/md5.h"
|
|
#include <string.h>
|
|
#include "generic/printf.h"
|
|
|
|
extern unsigned int random32(int type);
|
|
|
|
#ifndef USE_CPU_RANDOM
|
|
|
|
#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y))
|
|
#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y))
|
|
|
|
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
|
|
|
|
|
|
/*****************************/
|
|
/*** LOCAL DATA STRUCTURES ***/
|
|
/*****************************/
|
|
static char randPool[RANDPOOLSZ]; /* Pool of randomness. */
|
|
static long randCount = 0; /* Pseudo-random incrementer */
|
|
|
|
#endif
|
|
|
|
/***********************************/
|
|
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
|
/***********************************/
|
|
/*
|
|
* Initialize the random number generator.
|
|
*
|
|
* Since this is to be called on power up, we don't have much
|
|
* system randomess to work with. Here all we use is the
|
|
* real-time clock. We'll accumulate more randomness as soon
|
|
* as things start happening.
|
|
*/
|
|
void avRandomInit()
|
|
{
|
|
#ifndef USE_CPU_RANDOM
|
|
avChurnRand(NULL, 0);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Churn the randomness pool on a random event. Call this early and often
|
|
* on random and semi-random system events to build randomness in time for
|
|
* usage. For randomly timed events, pass a null pointer and a zero length
|
|
* and this will use the system timer and other sources to add randomness.
|
|
* If new random data is available, pass a pointer to that and it will be
|
|
* included.
|
|
*
|
|
*/
|
|
void avChurnRand(char *randData, uint32_t randLen)
|
|
{
|
|
#ifndef USE_CPU_RANDOM
|
|
mbedtls_md5_context md5;
|
|
|
|
mbedtls_md5_init(&md5);
|
|
mbedtls_md5_starts(&md5);
|
|
mbedtls_md5_update(&md5, (uint8_t *)randPool, sizeof(randPool));
|
|
|
|
if (randData) {
|
|
mbedtls_md5_update(&md5, (uint8_t *)randData, randLen);
|
|
} else {
|
|
struct {
|
|
/* INCLUDE fields for any system sources of randomness */
|
|
char foobar;
|
|
} sysData;
|
|
|
|
/* Load sysData fields here. */
|
|
mbedtls_md5_update(&md5, (uint8_t *)&sysData, sizeof(sysData));
|
|
}
|
|
|
|
mbedtls_md5_finish(&md5, (uint8_t *)randPool);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Use the random pool to generate random data. This degrades to pseudo
|
|
* random when used faster than randomness is supplied using churnRand().
|
|
* Note: It's important that there be sufficient randomness in randPool
|
|
* before this is called for otherwise the range of the result may be
|
|
* narrow enough to make a search feasible.
|
|
*
|
|
* XXX Why does he not just call churnRand() for each block? Probably
|
|
* so that you don't ever publish the seed which could possibly help
|
|
* predict future values.
|
|
* XXX Why don't we preserve md5 between blocks and just update it with
|
|
* randCount each time? Probably there is a weakness but I wish that
|
|
* it was documented.
|
|
*/
|
|
void avGenRand(char *buf, uint32_t bufLen)
|
|
{
|
|
#ifndef USE_CPU_RANDOM
|
|
mbedtls_md5_context md5;
|
|
uint8_t tmp[16];
|
|
uint32_t n;
|
|
|
|
while (bufLen > 0) {
|
|
n = LWIP_MIN(bufLen, RANDPOOLSZ);
|
|
mbedtls_md5_init(&md5);
|
|
mbedtls_md5_starts(&md5);
|
|
mbedtls_md5_update(&md5, (uint8_t *)randPool, sizeof(randPool));
|
|
mbedtls_md5_update(&md5, (uint8_t *)&randCount, sizeof(randCount));
|
|
mbedtls_md5_finish(&md5, tmp);
|
|
randCount++;
|
|
memcpy(buf, tmp, n);
|
|
buf += n;
|
|
bufLen -= n;
|
|
}
|
|
#else
|
|
const char *metachar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
|
|
memset(buf, 0, bufLen);
|
|
for (uint32_t i = 0; i < bufLen; i++) {
|
|
*(buf + i) = metachar[random32(0) % 62];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Return a new random number.
|
|
*/
|
|
uint32_t avRandom(void)
|
|
{
|
|
uint32_t newRand;
|
|
|
|
#ifndef USE_CPU_RANDOM
|
|
avGenRand((char *)&newRand, sizeof(newRand));
|
|
#else
|
|
newRand = random32(0);
|
|
#endif
|
|
|
|
return newRand;
|
|
}
|
|
|
|
int echo_cloud_get_hmac_sha256(const char *device_id, const char *channel_uuid, const char *nonce, char *signature, const char *hash_key)
|
|
{
|
|
unsigned char output[32] = {0};
|
|
char input[128 + 1] = {0};
|
|
|
|
snprintf(input, sizeof(input), "%s%s%s", channel_uuid, device_id, nonce);
|
|
|
|
if (0 != mbedtls_md_hmac(&mbedtls_sha256_info, (unsigned char *)hash_key, strlen(hash_key), (unsigned char *)input, strlen(input), output)) {
|
|
return -1;
|
|
}
|
|
for (unsigned char i = 0; i < 32; i++) {
|
|
sprintf(signature + i * 2, "%02x", (unsigned int)output[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|