Use the HWRNG for generating DUIDs and IAIDs.

Before these were generated from a freshly seeded PRNG which reduces the
state space of possible DUIDs and skews the distribution of both DUIDs
and IAIDs as a function of the PRNG choice.

None of this really matters much in practice, but do things right.
This commit is contained in:
Nicholas J. Kain 2022-08-28 03:52:44 -04:00
parent d43fc12306
commit 1f0a8f29de
No known key found for this signature in database
6 changed files with 19 additions and 26 deletions

View File

@ -1,4 +1,4 @@
// Copyright 2014-2018 Nicholas J. Kain <njkain at gmail dot com> // Copyright 2014-2022 Nicholas J. Kain <njkain at gmail dot com>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -11,7 +11,7 @@
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#include "nk/log.h" #include "nk/log.h"
#include "nk/random.h" #include "nk/hwrng.h"
#include "nk/io.h" #include "nk/io.h"
#include "duiaid.h" #include "duiaid.h"
#include "ndhc.h" #include "ndhc.h"
@ -90,8 +90,7 @@ static int open_iaidfile_write(const uint8_t hwaddr[static 6],
// RFC6355 specifies a RFC4122 UUID, but I simply use a 128-byte random // RFC6355 specifies a RFC4122 UUID, but I simply use a 128-byte random
// value, as the complexity of RFC4122 UUID generation is completely // value, as the complexity of RFC4122 UUID generation is completely
// unwarranted for DHCPv4. // unwarranted for DHCPv4.
static size_t generate_duid(struct nk_random_state *s, static size_t generate_duid(char *dest, size_t dlen)
char *dest, size_t dlen)
{ {
const size_t tlen = sizeof(uint16_t) + 4 * sizeof(uint32_t); const size_t tlen = sizeof(uint16_t) + 4 * sizeof(uint32_t);
if (dlen < tlen) if (dlen < tlen)
@ -102,32 +101,27 @@ static size_t generate_duid(struct nk_random_state *s,
memcpy(dest+off, &typefield, sizeof typefield); memcpy(dest+off, &typefield, sizeof typefield);
off += sizeof typefield; off += sizeof typefield;
for (size_t i = 0; i < 4; ++i) { nk_hwrng_bytes(dest+off, sizeof(uint32_t) * 4);
uint32_t r32 = nk_random_u32(s); off += sizeof(uint32_t) * 4;
memcpy(dest+off, &r32, sizeof r32);
off += sizeof r32;
}
return off; return off;
} }
// RFC6355 specifies the IAID as a 32-bit value that uniquely identifies // RFC6355 specifies the IAID as a 32-bit value that uniquely identifies
// a hardware link for a given host. // a hardware link for a given host.
static size_t generate_iaid(struct nk_random_state *s, static size_t generate_iaid(char *dest, size_t dlen)
char *dest, size_t dlen)
{ {
if (dlen < sizeof(uint32_t)) if (dlen < sizeof(uint32_t))
suicide("%s: dlen < %zu", __func__, sizeof(uint32_t)); suicide("%s: dlen < %zu", __func__, sizeof(uint32_t));
size_t off = 0; size_t off = 0;
uint32_t r32 = nk_random_u32(s); nk_hwrng_bytes(dest+off, sizeof(uint32_t));
memcpy(dest+off, &r32, sizeof r32); off += sizeof(uint32_t);
off += sizeof r32;
return off; return off;
} }
// Failures are all fatal. // Failures are all fatal.
void get_clientid(struct client_state_t *cs, void get_clientid(struct client_config_t *cc)
struct client_config_t *cc)
{ {
if (cc->clientid_len > 0) if (cc->clientid_len > 0)
return; return;
@ -138,7 +132,7 @@ void get_clientid(struct client_state_t *cs,
int fd = open_iaidfile_read(cc->arp, sizeof cc->arp); int fd = open_iaidfile_read(cc->arp, sizeof cc->arp);
if (fd < 0) { if (fd < 0) {
iaid_len = generate_iaid(&cs->rnd_state, iaid, sizeof iaid); iaid_len = generate_iaid(iaid, sizeof iaid);
fd = open_iaidfile_write(cc->arp, sizeof cc->arp); fd = open_iaidfile_write(cc->arp, sizeof cc->arp);
ssize_t r = safe_write(fd, iaid, iaid_len); ssize_t r = safe_write(fd, iaid, iaid_len);
if (r < 0 || (size_t)r != iaid_len) if (r < 0 || (size_t)r != iaid_len)
@ -155,7 +149,7 @@ void get_clientid(struct client_state_t *cs,
fd = open_duidfile_read(); fd = open_duidfile_read();
if (fd < 0) { if (fd < 0) {
duid_len = generate_duid(&cs->rnd_state, duid, sizeof duid); duid_len = generate_duid(duid, sizeof duid);
fd = open_duidfile_write(); fd = open_duidfile_write();
ssize_t r = safe_write(fd, duid, duid_len); ssize_t r = safe_write(fd, duid, duid_len);
if (r < 0 || (size_t)r != duid_len) if (r < 0 || (size_t)r != duid_len)

View File

@ -1,11 +1,11 @@
// Copyright 2014-2018 Nicholas J. Kain <njkain at gmail dot com> // Copyright 2014-2022 Nicholas J. Kain <njkain at gmail dot com>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#ifndef NJK_NDHC_DUIAID_H_ #ifndef NJK_NDHC_DUIAID_H_
#define NJK_NDHC_DUIAID_H_ #define NJK_NDHC_DUIAID_H_
#include "ndhc.h" #include "ndhc.h"
void get_clientid(struct client_state_t *cs, struct client_config_t *cc); void get_clientid(struct client_config_t *cc);
#endif #endif

2
ndhc.c
View File

@ -567,7 +567,7 @@ int main(int argc, char *argv[])
if (nl_getifdata() < 0) if (nl_getifdata() < 0)
suicide("failed to get interface MAC or index"); suicide("failed to get interface MAC or index");
get_clientid(&cs, &client_config); get_clientid(&client_config);
switch (perform_ifup()) { switch (perform_ifup()) {
case 1: case 0: break; case 1: case 0: break;

View File

@ -95,7 +95,7 @@ static bool nk_get_urandom(char *seed, size_t len)
return ret; return ret;
} }
void nk_get_hwrng(void *seed, size_t len) void nk_hwrng_bytes(void *seed, size_t len)
{ {
char *s = (char *)seed; char *s = (char *)seed;
if (nk_getrandom(s, len)) if (nk_getrandom(s, len))

View File

@ -1,11 +1,10 @@
// Copyright 2016 Nicholas J. Kain <njkain at gmail dot com> // Copyright 2016-2022 Nicholas J. Kain <njkain at gmail dot com>
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
#ifndef NCMLIB_HWCRNG__ #ifndef NCMLIB_HWCRNG__
#define NCMLIB_HWCRNG__ #define NCMLIB_HWCRNG__
#include <stddef.h> #include <stddef.h>
void nk_hwrng_bytes(void *seed, size_t len);
void nk_get_hwrng(void *seed, size_t len);
#endif #endif

View File

@ -8,7 +8,7 @@
void nk_random_init(struct nk_random_state *s) void nk_random_init(struct nk_random_state *s)
{ {
nk_get_hwrng(s->seed, sizeof(uint64_t) * 2); nk_hwrng_bytes(s->seed, sizeof(uint64_t) * 2);
s->seed[2] = 2000001; s->seed[2] = 2000001;
s->seed[3] = 0; s->seed[3] = 0;
for (size_t i = 0; i < 14; ++i) nk_random_u64(s); for (size_t i = 0; i < 14; ++i) nk_random_u64(s);