1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

sys/luid: improve luid_base() algorithm

CPU IDs may contain very little entropy. Often only a single byte
may change between two CPUs.

To mitigate this use a somewhat 'proper' hash algorithm (I chose DJB2
hash simply because it's small) and 'extend' it to the required output
size.

For 50 STM32 CPU IDs from the grenoble site, this produces a much more
random LUID output.
This commit is contained in:
Benjamin Valentin 2020-10-18 14:06:19 +02:00
parent 652aac4e57
commit 6fa15ff3f6

View File

@ -26,8 +26,17 @@
#include "luid.h"
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#if CPUID_LEN
/* based on DJB2 Hash */
static void _luid_round(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len)
{
uint32_t hash = 5381;
for (size_t i = 0; i < in_len; i++) {
hash = hash * 33 + in[i];
out[i % out_len] ^= hash;
}
}
#endif
void __attribute__((weak)) luid_base(void *buf, size_t len)
@ -35,34 +44,11 @@ void __attribute__((weak)) luid_base(void *buf, size_t len)
memset(buf, LUID_BACKUP_SEED, len);
#if CPUID_LEN
uint8_t *out = buf;
uint8_t cid[CPUID_LEN];
uint8_t sum = 0;
cpuid_get(cid);
/* CPU ID is XORed with LUID_BACKUP_SEED.
* Then FisherYates shuffle is performed to mix
* the bytes, as often large continuous chunks of
* CPU ID are equal on machines with the same CPU.
*/
for (size_t i = 0; i < MAX(len, CPUID_LEN); i++) {
uint8_t tmp, j, k;
j = i % len;
k = i % CPUID_LEN;
/* xor with CPU ID */
out[j] ^= cid[k];
/* get 'random' position */
sum += out[j];
k = sum % (j + 1);
/* shuffle bytes */
tmp = out[j];
out[j] = out[k];
out[k] = tmp;
}
_luid_round(cid, sizeof(cid), buf, len);
_luid_round(buf, len, buf, len);
#endif
}