Index: ossp-pkg/uuid/Makefile.in RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/Makefile.in,v rcsdiff -q -kk '-r1.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/Makefile.in,v' 2>/dev/null --- Makefile.in 2004/01/09 15:49:40 1.4 +++ Makefile.in 2004/01/10 12:16:03 1.5 @@ -50,7 +50,7 @@ POD2MAN = pod2man LIB_NAME = libuuid.la -LIB_OBJS = uuid.lo uuid_md5.lo uuid_ui64.lo +LIB_OBJS = uuid.lo uuid_md5.lo uuid_prng.lo uuid_ui64.lo PRG_NAME = uuid PRG_OBJS = uuid_cli.o Index: ossp-pkg/uuid/uuid.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v rcsdiff -q -kk '-r1.13' '-r1.14' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.c,v' 2>/dev/null --- uuid.c 2004/01/10 11:54:05 1.13 +++ uuid.c 2004/01/10 12:16:03 1.14 @@ -41,6 +41,7 @@ #include "config.h" #include "uuid.h" #include "uuid_md5.h" +#include "uuid_prng.h" #include "uuid_ui64.h" /* determine types of 8-bit size */ @@ -118,7 +119,9 @@ /* abstract data type (ADT) of API */ struct uuid_st { - uuid_obj_t obj; + uuid_obj_t obj; /* inlined UUID object */ + prng_t *prng; /* RPNG sub-object */ + md5_t *md5; /* MD5 sub-object */ }; /* create UUID object */ @@ -128,13 +131,19 @@ if (uuid == NULL) return UUID_RC_ARG; - /* allocate UUID binary representation buffer */ + /* allocate UUID object */ if ((*uuid = (uuid_t *)malloc(sizeof(uuid_t))) == NULL) return UUID_RC_MEM; - /* set initially to "nil UUID" */ + /* set UUID object initially to "nil UUID" */ uuid_nil(*uuid); + /* create PRNG and MD5 sub-objects */ + if (prng_create(&(*uuid)->prng) != PRNG_RC_OK) + return UUID_RC_INT; + if (md5_create(&(*uuid)->md5) != MD5_RC_OK) + return UUID_RC_INT; + return UUID_RC_OK; } @@ -145,7 +154,11 @@ if (uuid == NULL) return UUID_RC_ARG; - /* free UUID binary representation buffer */ + /* destroy PRNG and MD5 sub-objects */ + prng_destroy(uuid->prng); + md5_destroy(uuid->md5); + + /* free UUID object */ free(uuid); return UUID_RC_OK; @@ -432,68 +445,6 @@ return UUID_RC_OK; } -/* INTERNAL: pseudo-random number generator (PRNG) */ -static void uuid_prng_getdata(uuid_uint8_t *data_ptr, size_t data_len) -{ - static int initialized = FALSE; - static int fd = -1; - struct timeval tv; - pid_t pid; - size_t n; - size_t i; - uuid_uint8_t *p; - int cnt; - - if (!initialized) { - /* try to open the system PRNG device */ - if ((fd = open("/dev/urandom", O_RDONLY)) == -1) - fd = open("/dev/random", O_RDONLY|O_NONBLOCK); - if (fd != -1) - fcntl(fd, F_SETFD, FD_CLOEXEC); - - /* seed the PRNG once */ - gettimeofday(&tv, NULL); - pid = getpid(); - srand((unsigned int)( - ((uuid_uint32_t)pid << 16) - ^ (uuid_uint32_t)pid - ^ (uuid_uint32_t)tv.tv_sec - ^ (uuid_uint32_t)tv.tv_usec)); - - /* crank the PRNG a few times */ - gettimeofday(&tv, NULL); - for (i = (unsigned int)(tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) - (void)rand(); - - initialized = TRUE; - } - - /* try to gather data from the system PRNG device */ - if (fd != -1) { - p = data_ptr; - n = data_len; - cnt = 0; - while (n > 0) { - i = read(fd, (void *)p, n); - if (i <= 0) { - if (cnt++ > 16) - break; - continue; - } - n -= i; - p += i; - cnt = 0; - } - } - - /* 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 = data_ptr, n = 0; n < data_len; n++) - *p++ ^= (uuid_uint8_t)(((uuid_uint32_t)rand() >> 7) & 0xFF); - - return; -} - /* INTERNAL: brand UUID with version and variant */ static void uuid_brand(uuid_t *uuid, int version) { @@ -542,7 +493,6 @@ void *uuid_octets; uuid_t *uuid_object; uuid_rc_t rc; - md5_t *md5; int i; /* determine namespace UUID name and argument name string */ @@ -551,8 +501,8 @@ if ((str = (char *)va_arg(ap, char *)) == NULL) return UUID_RC_ARG; - /* create MD5 context */ - if (md5_create(&md5) != MD5_RC_OK) + /* initialize MD5 context */ + if (md5_init(uuid->md5) != MD5_RC_OK) return UUID_RC_MEM; /* load the namespace UUID into MD5 context */ @@ -564,7 +514,7 @@ return rc; uuid_octets = (void *)&(uuid_object->obj); uuid_pack(uuid_object, &uuid_octets); - md5_update(md5, uuid_octets, UUID_LEN_BIN); + md5_update(uuid->md5, uuid_octets, UUID_LEN_BIN); uuid_destroy(uuid_object); } else { @@ -578,20 +528,17 @@ } if (uuid_octets == NULL) return UUID_RC_ARG; - md5_update(md5, uuid_octets, UUID_LEN_BIN); + md5_update(uuid->md5, uuid_octets, UUID_LEN_BIN); } /* load the argument name string into MD5 context */ - md5_update(md5, str, strlen(str)); + md5_update(uuid->md5, str, strlen(str)); /* store MD5 result into UUID (requires MD5_LEN_BIN space, UUID_LEN_BIN space is available, and both are equal in size, so we are safe!) */ uuid_octets = (void *)&(uuid->obj); - md5_store(md5, &uuid_octets, NULL); - - /* destroy MD5 context */ - md5_destroy(md5); + md5_store(uuid->md5, &uuid_octets, NULL); /* fulfill requirement of standard and convert UUID data into local/host byte order (this uses fact that uuid_unpack() is @@ -608,7 +555,7 @@ static uuid_rc_t uuid_generate_v4(uuid_t *uuid, unsigned int mode, va_list ap) { /* fill UUID with random data */ - uuid_prng_getdata((void *)&(uuid->obj), sizeof(uuid->obj)); + prng_data(uuid->prng, (void *)&(uuid->obj), sizeof(uuid->obj)); /* brand UUID with version and variant */ uuid_brand(uuid, 4); Index: ossp-pkg/uuid/uuid.h RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.h,v rcsdiff -q -kk '-r1.6' '-r1.7' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid.h,v' 2>/dev/null --- uuid.h 2004/01/09 16:11:40 1.6 +++ uuid.h 2004/01/10 12:16:03 1.7 @@ -76,7 +76,8 @@ UUID_RC_OK = 0, UUID_RC_ARG = 1, UUID_RC_MEM = 2, - UUID_RC_SYS = 3 + UUID_RC_SYS = 3, + UUID_RC_INT = 4 } uuid_rc_t; /* generation mode flags */ Index: ossp-pkg/uuid/uuid_md5.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_md5.c,v rcsdiff -q -kk '-r1.3' '-r1.4' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_md5.c,v' 2>/dev/null --- uuid_md5.c 2004/01/10 10:49:00 1.3 +++ uuid_md5.c 2004/01/10 12:16:03 1.4 @@ -367,6 +367,14 @@ return MD5_RC_OK; } +md5_rc_t md5_init(md5_t *md5) +{ + if (md5 == NULL) + return MD5_RC_ARG; + MD5Init(&(md5->ctx)); + return MD5_RC_OK; +} + md5_rc_t md5_update(md5_t *md5, const void *data_ptr, size_t data_len) { if (md5 == NULL) Index: ossp-pkg/uuid/uuid_md5.h RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_md5.h,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_md5.h,v' 2>/dev/null --- uuid_md5.h 2004/01/09 15:49:40 1.1 +++ uuid_md5.h 2004/01/10 12:16:03 1.2 @@ -65,6 +65,7 @@ } md5_rc_t; extern md5_rc_t md5_create (md5_t **md5); +extern md5_rc_t md5_init (md5_t *md5); extern md5_rc_t md5_update (md5_t *md5, const void *data_ptr, size_t data_len); extern md5_rc_t md5_store (md5_t *md5, void **data_ptr, size_t *data_len); extern md5_rc_t md5_format (md5_t *md5, char **data_ptr, size_t *data_len); Index: ossp-pkg/uuid/uuid_prng.c RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.c,v' | diff -u /dev/null - -L'ossp-pkg/uuid/uuid_prng.c' 2>/dev/null --- ossp-pkg/uuid/uuid_prng.c +++ - 2024-05-17 00:30:02.882444032 +0200 @@ -0,0 +1,132 @@ +/* +** OSSP uuid - Universally Unique Identifier +** Copyright (c) 2004 Ralf S. Engelschall +** Copyright (c) 2004 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 +*/ + +#include +#include +#include +#include +#include +#include + +#include "uuid_prng.h" + +struct prng_st { + int devfd; +}; + +prng_rc_t prng_create(prng_t **prng) +{ + int fd = -1; + struct timeval tv; + pid_t pid; + size_t 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)->devfd = -1; + if ((fd = open("/dev/urandom", O_RDONLY)) == -1) + fd = open("/dev/random", O_RDONLY|O_NONBLOCK); + if (fd != -1) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + (*prng)->devfd = fd; + } + + /* seed the C library PRNG once */ + gettimeofday(&tv, NULL); + pid = getpid(); + srand((unsigned int)( + ((unsigned int)pid << 16) + ^ (unsigned int)pid + ^ (unsigned int)tv.tv_sec + ^ (unsigned int)tv.tv_usec)); + + /* crank the PRNG a few times */ + gettimeofday(&tv, NULL); + 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; + int cnt; + int i; + + /* sanity check argument(s) */ + if (prng == NULL || data_len == 0) + return PRNG_RC_ARG; + + /* try to gather data from the system PRNG device */ + if (prng->devfd != -1) { + p = data_ptr; + n = data_len; + cnt = 0; + while (n > 0) { + i = read(prng->devfd, (void *)p, n); + if (i <= 0) { + if (cnt++ > 16) + break; + continue; + } + n -= i; + p += i; + cnt = 0; + } + } + + /* 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 = data_ptr, n = 0; n < data_len; n++) + *p++ ^= (unsigned char)(((unsigned int)rand() >> 7) & 0xFF); + + return PRNG_RC_OK; +} + +prng_rc_t prng_destroy(prng_t *prng) +{ + /* sanity check argument(s) */ + if (prng == NULL) + return PRNG_RC_ARG; + + /* free object */ + free(prng); + + return PRNG_RC_OK; +} + Index: ossp-pkg/uuid/uuid_prng.h RCS File: /v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/uuid/Attic/uuid_prng.h,v' | diff -u /dev/null - -L'ossp-pkg/uuid/uuid_prng.h' 2>/dev/null --- ossp-pkg/uuid/uuid_prng.h +++ - 2024-05-17 00:30:02.885104580 +0200 @@ -0,0 +1,67 @@ +/* +** OSSP uuid - Universally Unique Identifier +** Copyright (c) 2004 Ralf S. Engelschall +** Copyright (c) 2004 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.h: PRNG API definition +*/ + +#ifndef __PRNG_H___ +#define __PRNG_H___ + +#include /* size_t */ + +#define PRNG_PREFIX uuid_ + +/* embedding support */ +#ifdef PRNG_PREFIX +#if defined(__STDC__) || defined(__cplusplus) +#define __PRNG_CONCAT(x,y) x ## y +#define PRNG_CONCAT(x,y) __PRNG_CONCAT(x,y) +#else +#define __PRNG_CONCAT(x) x +#define PRNG_CONCAT(x,y) __PRNG_CONCAT(x)y +#endif +#define prng_st PRNG_CONCAT(PRNG_PREFIX,prng_st) +#define prng_t PRNG_CONCAT(PRNG_PREFIX,prng_t) +#define prng_create PRNG_CONCAT(PRNG_PREFIX,prng_create) +#define prng_data PRNG_CONCAT(PRNG_PREFIX,prng_data) +#define prng_destroy PRNG_CONCAT(PRNG_PREFIX,prng_destroy) +#endif + +struct prng_st; +typedef struct prng_st prng_t; + +typedef enum { + PRNG_RC_OK = 0, + PRNG_RC_ARG = 1, + PRNG_RC_MEM = 2 +} prng_rc_t; + +extern prng_rc_t prng_create (prng_t **prng); +extern prng_rc_t prng_data (prng_t *prng, void *data_ptr, size_t data_len); +extern prng_rc_t prng_destroy (prng_t *prng); + +#endif /* __PRNG_H___ */ +