Module Name: src Committed By: riastradh Date: Sat Oct 4 10:30:13 UTC 2014
Modified Files: src/sbin/gpt: gpt_uuid.c Log Message: Make gpt(8) generate v4 (random) uuids. Don't needlessly leak your date/time and MAC address when you edit the disk. Read from /dev/urandom rather than calling arc4random or anything, since this is a tool. (Cygwin seems to have /dev/urandom, but yell if this breaks the build on your exotic platform because it lacks /dev/urandom.) ok apb To generate a diff of this commit: cvs rdiff -u -r1.7 -r1.8 src/sbin/gpt/gpt_uuid.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/gpt/gpt_uuid.c diff -u src/sbin/gpt/gpt_uuid.c:1.7 src/sbin/gpt/gpt_uuid.c:1.8 --- src/sbin/gpt/gpt_uuid.c:1.7 Fri Oct 3 20:30:06 2014 +++ src/sbin/gpt/gpt_uuid.c Sat Oct 4 10:30:13 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: gpt_uuid.c,v 1.7 2014/10/03 20:30:06 christos Exp $ */ +/* $NetBSD: gpt_uuid.c,v 1.8 2014/10/04 10:30:13 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,10 +32,13 @@ #include <sys/cdefs.h> #ifdef __RCSID -__RCSID("$NetBSD: gpt_uuid.c,v 1.7 2014/10/03 20:30:06 christos Exp $"); +__RCSID("$NetBSD: gpt_uuid.c,v 1.8 2014/10/04 10:30:13 riastradh Exp $"); #endif +#include <err.h> +#include <fcntl.h> #include <stdio.h> +#include <unistd.h> #include "map.h" #include "gpt.h" @@ -56,12 +59,6 @@ struct dce_uuid { uint8_t node[6]; }; -struct kern_uuid { - uint64_t ll; - uint16_t seq; - uint8_t node[6]; -}; - static const struct { struct dce_uuid u; const char *n; @@ -238,96 +235,35 @@ gpt_uuid_create(gpt_type_t t, gpt_uuid_t utf8_to_utf16((const uint8_t *)gpt_nv[t].d, b, s / sizeof(*b)); } -#if !defined(HAVE_NBTOOL_CONFIG_H) -#include <sys/types.h> -#include <sys/uuid.h> -#else -#include <time.h> -/* - * Get the current time as a 5x bit count of 100000-microsecond intervals - * since 00:00:00.00, October 15,1582. We apply a magic offset to convert - * the Unix time since 00:00:00.00, January 1, 1970 to the date of the - * Gregorian reform to the Christian calendar. - */ -static uint64_t -uuid_time(void) -{ - struct timeval tv; - uint64_t xtime = 0x01B21DD213814000LL; - - (void)gettimeofday(&tv, NULL); - xtime += (uint64_t)tv.tv_sec * 10000000LL; - xtime += (uint64_t)(tv.tv_usec / 100000); - return (xtime & ((1LL << 60) - 1LL)); -} - -/* - * No portable way to get ethernet, use hostid instead - */ -static void -uuid_node(uint8_t node[6]) -{ - long hid = gethostid(); - node[0] = 'N'; - node[1] = 'B'; - node[2] = (hid >> 24) & 0xff; - node[3] = (hid >> 16) & 0xff; - node[4] = (hid >> 8) & 0xff; - node[5] = (hid >> 0) & 0xff; -} - -static void -uuid_generate(void *u, uint64_t *timep, int count) -{ - static struct kern_uuid uuid_last; - uint64_t xtime, ltime; - uint16_t lseq; - struct kern_uuid *uuid = u; - - uuid_node(uuid->node); - xtime = uuid_time(); - *timep = xtime; - - if (uuid_last.ll == 0LL || uuid_last.node[0] != uuid->node[0] || - uuid_last.node[1] != uuid->node[1] || - uuid_last.node[2] != uuid->node[2]) { - srandom((unsigned int) xtime); - uuid->seq = (uint16_t)random() & 0x3fff; - } else if (uuid_last.ll >= xtime) - uuid->seq = (uuid_last.seq + 1) & 0x3fff; - - uuid_last = *uuid; - uuid_last.ll = (xtime + count - 1) & ((1LL << 60) - 1LL); -} - -static void -uuidgen(struct dce_uuid *store, int count) -{ - uint64_t xtime; - struct kern_uuid uuid; - int i; - - /* Generate the base UUID. */ - uuid_generate(&uuid, &xtime, count); - - for (i = 0; i < count; xtime++, i++) { - /* Set time and version (=1) and deal with byte order. */ - store[i].time_low = (uint32_t)xtime; - store[i].time_mid = (uint16_t)(xtime >> 32); - store[i].time_hi_and_version = - ((uint16_t)(xtime >> 48) & 0xfff) | (1 << 12); - store[i].clock_seq_hi_and_reserved = (uuid.seq >> 16) | 0x80; - store[i].clock_seq_low = uuid.seq & 0xff; - memcpy(store[i].node, uuid.node, sizeof(uuid.node)); - } -} -#endif - void gpt_uuid_generate(gpt_uuid_t t) { struct dce_uuid u; + int fd; + uint8_t *p; + size_t n; + ssize_t nread; + + /* Randomly generate the content. */ + fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) + err(1, "open(/dev/urandom)"); + for (p = (void *)&u, n = sizeof u; 0 < n; p += nread, n -= nread) { + nread = read(fd, p, n); + if (nread < 0) + err(1, "read(/dev/urandom)"); + if ((size_t)nread > n) + errx(1, "read too much: %zd > %zu", nread, n); + } + (void)close(fd); + + /* Set the version number to 4. */ + u.time_hi_and_version &= ~(uint32_t)0xf000; + u.time_hi_and_version |= 0x4000; + + /* Fix the reserved bits. */ + u.clock_seq_hi_and_reserved &= ~(uint8_t)0x40; + u.clock_seq_hi_and_reserved |= 0x80; - uuidgen((void *)&u, 1); gpt_dce_to_uuid(&u, t); }