head 1.21; access; symbols UUID_1_6_2:1.20 UUID_1_6_1:1.18 UUID_1_6_0:1.15 UUID_1_5_1:1.12 UUID_1_5_0:1.12 UUID_1_4_2:1.11 UUID_1_4_1:1.11 UUID_1_4_0:1.11 UUID_1_3_2:1.10 UUID_1_3_1:1.10 UUID_1_3_0:1.8 UUID_1_2_1:1.8 UUID_1_2_0:1.4 UUID_1_1_2:1.4 UUID_1_1_1:1.3 UUID_1_1_0:1.3 UUID_1_0_4:1.3 UUID_1_0_3:1.3 UUID_1_0_2:1.3 UUID_1_0_1:1.3 UUID_1_0_0:1.3 UUID_0_9_7:1.3 UUID_0_9_6:1.3 UUID_0_9_5:1.3 UUID_0_9_4:1.2 UUID_0_9_3:1.1 UUID_0_9_2:1.1 UUID_0_9_1:1.1 UUID_0_9_0:1.1; locks; strict; comment @ * @; 1.21 date 2008.07.05.12.58.17; author rse; state dead; branches; next 1.20; commitid XLXN7vUmABwPcC9t; 1.20 date 2008.06.04.17.27.27; author rse; state Exp; branches; next 1.19; commitid ho0aNi4QXNYYGE5t; 1.19 date 2008.03.06.12.14.49; author rse; state Exp; branches; next 1.18; commitid DMtu1kD8JmZZQ3Us; 1.18 date 2008.02.21.15.34.51; author rse; state Exp; branches; next 1.17; commitid byWeYC7uJCoBphSs; 1.17 date 2008.02.21.08.58.45; author rse; state Exp; branches; next 1.16; commitid 49UAeQtix4DIdfSs; 1.16 date 2008.01.10.14.18.47; author rse; state Exp; branches; next 1.15; commitid LqMgFGBgTR7clSMs; 1.15 date 2007.01.01.18.14.55; author rse; state Exp; branches; next 1.14; commitid jOXiIO8S8v7xFP0s; 1.14 date 2006.08.02.13.11.09; author rse; state Exp; branches; next 1.13; commitid fwUmuuaIDS3gSgHr; 1.13 date 2006.08.02.11.59.08; author rse; state Exp; branches; next 1.12; commitid YijM0y8Y7mFytgHr; 1.12 date 2006.07.28.19.16.03; author rse; state Exp; branches; next 1.11; commitid atQ0Apen8cBq3FGr; 1.11 date 2006.01.13.06.44.31; author rse; state Exp; branches; next 1.10; commitid hYfQc9JIMh4bcphr; 1.10 date 2005.09.24.10.28.32; author rse; state Exp; branches; next 1.9; 1.9 date 2005.09.20.20.29.10; author rse; state Exp; branches; next 1.8; 1.8 date 2005.08.30.19.25.04; author rse; state Exp; branches; next 1.7; 1.7 date 2005.08.30.18.41.56; author rse; state Exp; branches; next 1.6; 1.6 date 2005.08.30.15.26.07; author rse; state Exp; branches; next 1.5; 1.5 date 2005.03.29.19.01.41; author rse; state Exp; branches; next 1.4; 1.4 date 2004.12.31.19.20.34; author rse; state Exp; branches; next 1.3; 1.3 date 2004.02.04.06.24.28; author rse; state Exp; branches; next 1.2; 1.2 date 2004.01.18.19.22.54; author rse; state Exp; branches; next 1.1; 1.1 date 2004.01.10.12.16.03; author rse; state Exp; branches; next ; desc @@ 1.21 log @remove OSSP uuid from CVS -- it is now versioned controlled in a Monotone repository @ text @/* ** OSSP uuid - Universally Unique Identifier ** Copyright (c) 2004-2008 Ralf S. Engelschall ** Copyright (c) 2004-2008 The OSSP Project ** ** This file is part of OSSP uuid, a library for the generation ** of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/ ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** uuid_prng.c: PRNG API implementation */ /* own headers (part 1/2) */ #include "uuid_ac.h" /* system headers */ #include #include #include #include #include #include #if defined(WIN32) #define WINVER 0x0500 #include #include #endif /* own headers (part 2/2) */ #include "uuid_time.h" #include "uuid_prng.h" #include "uuid_md5.h" struct prng_st { int dev; /* system PRNG device */ md5_t *md5; /* local MD5 PRNG engine */ long cnt; /* time resolution compensation counter */ }; prng_rc_t prng_create(prng_t **prng) { #if !defined(WIN32) int fd = -1; #endif struct timeval tv; pid_t pid; unsigned int i; /* sanity check argument(s) */ if (prng == NULL) return PRNG_RC_ARG; /* allocate object */ if ((*prng = (prng_t *)malloc(sizeof(prng_t))) == NULL) return PRNG_RC_MEM; /* try to open the system PRNG device */ (*prng)->dev = -1; #if !defined(WIN32) if ((fd = open("/dev/urandom", O_RDONLY)) == -1) fd = open("/dev/random", O_RDONLY|O_NONBLOCK); if (fd != -1) { (void)fcntl(fd, F_SETFD, FD_CLOEXEC); (*prng)->dev = fd; } #endif /* initialize MD5 engine */ if (md5_create(&((*prng)->md5)) != MD5_RC_OK) { free(*prng); return PRNG_RC_INT; } /* initialize time resolution compensation counter */ (*prng)->cnt = 0; /* seed the C library PRNG once */ (void)time_gettimeofday(&tv); pid = getpid(); srand((unsigned int)( ((unsigned int)pid << 16) ^ (unsigned int)pid ^ (unsigned int)tv.tv_sec ^ (unsigned int)tv.tv_usec)); for (i = (unsigned int)((tv.tv_sec ^ tv.tv_usec) & 0x1F); i > 0; i--) (void)rand(); return PRNG_RC_OK; } prng_rc_t prng_data(prng_t *prng, void *data_ptr, size_t data_len) { size_t n; unsigned char *p; struct { struct timeval tv; long cnt; int rnd; } entropy; unsigned char md5_buf[MD5_LEN_BIN]; unsigned char *md5_ptr; size_t md5_len; int retries; int i; #if defined(WIN32) HCRYPTPROV hProv; #endif /* sanity check argument(s) */ if (prng == NULL || data_len == 0) return PRNG_RC_ARG; /* prepare for generation */ p = (unsigned char *)data_ptr; n = data_len; /* approach 1: try to gather data via stronger system PRNG device */ if (prng->dev != -1) { retries = 0; while (n > 0) { i = (int)read(prng->dev, (void *)p, n); if (i <= 0) { if (retries++ > 16) break; continue; } retries = 0; n -= (unsigned int)i; p += (unsigned int)i; } } #if defined(WIN32) else { if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) CryptGenRandom(hProv, n, p); } #endif /* approach 2: try to gather data via weaker libc PRNG API. */ while (n > 0) { /* gather new entropy */ (void)time_gettimeofday(&(entropy.tv)); /* source: libc time */ entropy.rnd = rand(); /* source: libc PRNG */ entropy.cnt = prng->cnt++; /* source: local counter */ /* pass entropy into MD5 engine */ if (md5_update(prng->md5, (void *)&entropy, sizeof(entropy)) != MD5_RC_OK) return PRNG_RC_INT; /* store MD5 engine state as PRN output */ md5_ptr = md5_buf; md5_len = sizeof(md5_buf); if (md5_store(prng->md5, (void **)(void *)&md5_ptr, &md5_len) != MD5_RC_OK) return PRNG_RC_INT; for (i = 0; i < MD5_LEN_BIN && n > 0; i++, n--) *p++ ^= md5_buf[i]; /* intentionally no assignment because arbitrary caller buffer content is leveraged, too */ } return PRNG_RC_OK; } prng_rc_t prng_destroy(prng_t *prng) { /* sanity check argument(s) */ if (prng == NULL) return PRNG_RC_ARG; /* close PRNG device */ if (prng->dev != -1) (void)close(prng->dev); /* destroy MD5 engine */ (void)md5_destroy(prng->md5); /* free object */ free(prng); return PRNG_RC_OK; } @ 1.20 log @Improve PRNG under Win32 @ text @@ 1.19 log @1. Remove unused "struct timezone" from time_gettimeofday() in order to simplify portability. 2. Add support for POSIX clock_gettime(3) in case the Unix/POSIX gettimeofday(3) is not available. @ text @d40 5 d122 3 d149 6 @ 1.18 log @fix remaining Win32 issues @ text @d90 1 a90 1 (void)time_gettimeofday(&tv, NULL); d145 3 a147 3 (void)time_gettimeofday(&(entropy.tv), NULL); /* source: libc time */ entropy.rnd = rand(); /* source: libc PRNG */ entropy.cnt = prng->cnt++; /* source: local counter */ @ 1.17 log @Port to Win32 API @ text @d42 1 d90 1 a90 1 (void)gettimeofday(&tv, NULL); d145 1 a145 1 (void)gettimeofday(&(entropy.tv), NULL); /* source: libc time */ @ 1.16 log @adjust copyright messages for 2008 and bump version in advance @ text @d53 1 d55 1 d70 1 d77 1 @ 1.15 log @Adjust copyright messages for new year 2007. @ text @d3 2 a4 2 ** Copyright (c) 2004-2007 Ralf S. Engelschall ** Copyright (c) 2004-2007 The OSSP Project @ 1.14 log @Optional DMALLOC based memory debugging support. @ text @d3 2 a4 2 ** Copyright (c) 2004-2006 Ralf S. Engelschall ** Copyright (c) 2004-2006 The OSSP Project @ 1.13 log @Consistently include "config.h" in all source files. @ text @d30 4 d41 1 a41 1 #include "config.h" @ 1.12 log @Even more pendantic code cleanups according to complains by SPLINT @ text @d37 1 @ 1.11 log @Adjust copyright messages for new year 2006. @ text @d51 1 a51 1 size_t i; d71 2 a72 1 if (md5_create(&((*prng)->md5)) != MD5_RC_OK) d74 1 d120 1 a120 1 i = read(prng->dev, (void *)p, n); d164 1 a164 1 close(prng->dev); d167 1 a167 1 md5_destroy(prng->md5); @ 1.10 log @Fix two incorrect casts, detected by compiling the C code under C++ constraints. @ text @d3 2 a4 2 ** Copyright (c) 2004-2005 Ralf S. Engelschall ** Copyright (c) 2004-2005 The OSSP Project @ 1.9 log @Plug memory leak in PRNG sub-library. Detected by valgrind(1). @ text @d144 1 a144 1 if (md5_store(prng->md5, (void *)&md5_ptr, &md5_len) != MD5_RC_OK) @ 1.8 log @annotate what the source really is @ text @d164 3 @ 1.7 log @cleanup Flexelint warnings @ text @d133 3 a135 3 (void)gettimeofday(&(entropy.tv), NULL); entropy.cnt = prng->cnt++; entropy.rnd = rand(); @ 1.6 log @Improve the PRNG in case no stronger system PRNG device is available by passing time and rand(3) based entropy into the MD5 one-way hash function to achieve at least some sort of weaker PRN data. @ text @d66 1 a66 1 fcntl(fd, F_SETFD, FD_CLOEXEC); d78 1 a78 1 gettimeofday(&tv, NULL); d133 1 a133 1 gettimeofday(&(entropy.tv), NULL); d138 2 a139 1 md5_update(prng->md5, (void *)&entropy, sizeof(entropy)); d144 2 a145 1 md5_store(prng->md5, (void *)&md5_ptr, &md5_len); @ 1.5 log @Cleanup the source code even more by following a large set of FlexeLint's suggestions. @ text @d38 1 d41 3 a43 1 int devfd; d62 1 a62 1 (*prng)->devfd = -1; d67 1 a67 1 (*prng)->devfd = fd; d70 7 d85 1 a85 4 /* crank the PRNG a few times */ gettimeofday(&tv, NULL); for (i = (unsigned int)(tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) d95 9 a103 1 int cnt; d110 7 a116 5 /* try to gather data from the system PRNG device */ if (prng->devfd != -1) { p = (unsigned char *)data_ptr; n = data_len; cnt = 0; d118 1 a118 1 i = read(prng->devfd, (void *)p, n); d120 1 a120 1 if (cnt++ > 16) d124 1 a126 1 cnt = 0; d130 18 a147 4 /* always also apply the weaker PRNG. In case the stronger PRNG device based source failed, this is the only remaining randomness, of course */ for (p = (unsigned char *)data_ptr, n = 0; n < data_len; n++) *p++ ^= (unsigned char)(((unsigned int)rand() >> 7) & 0xFF); d159 2 a160 2 if (prng->devfd != -1) close(prng->devfd); @ 1.4 log @Adjust copyright messages for new year 2005. @ text @d107 2 a108 2 n -= i; p += i; @ 1.3 log @Fixed filedescriptor leak in the PRNG sub-API. Submitted by: Guerry Semones @ text @d3 2 a4 2 ** Copyright (c) 2004 Ralf S. Engelschall ** Copyright (c) 2004 The OSSP Project @ 1.2 log @- Cleanup the C code to also pass warning-free a C++ compiler. - Support C++ by enclosing the C API declarations in 'extern "C" {...}' within uuid.h. Submitted by: Guerry Semones @ text @d127 4 @ 1.1 log @move out PRNG into own object and attach a PRNG and MD5 object for reuse into the UUID object @ text @d97 1 a97 1 p = data_ptr; d115 1 a115 1 for (p = data_ptr, n = 0; n < data_len; n++) @