From 6fa15ff3f64a9681e9e91f76ef8a38c63d06112c Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Sun, 18 Oct 2020 14:06:19 +0200 Subject: [PATCH] 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. --- sys/luid/luid.c | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/sys/luid/luid.c b/sys/luid/luid.c index a028bcc4a2..80555a8376 100644 --- a/sys/luid/luid.c +++ b/sys/luid/luid.c @@ -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 Fisher–Yates 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 }