"Fossies" - the Fresh Open Source Software Archive

Member "evolution-brutus-1.2.35/server/brutus_uuid.c" (9 Mar 2009, 40730 Bytes) of archive /linux/misc/old/evolution-brutus-1.2.35.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "brutus_uuid.c" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
    2 
    3 /*
    4 **  OSSP uuid - Universally Unique Identifier
    5 **  Copyright (c) 2004-2007 Ralf S. Engelschall <rse@engelschall.com>
    6 **  Copyright (c) 2004-2007 The OSSP Project <http://www.ossp.org/>
    7 **  Copyright (C) 2007 Jules Colding <colding@42tools.com>
    8 **
    9 **  This file is mainly composed of code which has been pillaged
   10 **  from OSSP uuid, a library for the generation of UUIDs which can
   11 **  be found at http://www.ossp.org/pkg/lib/uuid/
   12 **
   13 **  Permission to use, copy, modify, and distribute this software for
   14 **  any purpose with or without fee is hereby granted, provided that
   15 **  the above copyright notice and this permission notice appear in all
   16 **  copies.
   17 **
   18 **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   19 **  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   20 **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21 **  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
   22 **  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   23 **  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   24 **  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   25 **  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   26 **  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   27 **  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   28 **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29 **  SUCH DAMAGE.
   30 **
   31 **  brutus_uuid.c: UUID creation function
   32 */
   33 
   34 #ifdef HAVE_CONFIG_H
   35 #   include <config.h>
   36 #endif
   37 
   38 /* system headers */
   39 #include <glib.h>
   40 #include <glib/gprintf.h>
   41 #include <string.h>
   42 #include <ctype.h>
   43 #include <fcntl.h>
   44 #ifdef HAVE_SYS_TIME_H
   45 #   include <sys/time.h>
   46 #endif
   47 #ifdef HAVE_SYS_TYPES_H
   48 #   include <sys/types.h>
   49 #endif
   50 #ifdef HAVE_SYS_PARAM_H
   51 #   include <sys/param.h>
   52 #endif
   53 #ifdef HAVE_SYS_IOCTL_H
   54 #   include <sys/ioctl.h>
   55 #endif
   56 #ifdef HAVE_SYS_SOCKET_H
   57 #   include <sys/socket.h>
   58 #endif
   59 #ifdef HAVE_SYS_SOCKIO_H
   60 #   include <sys/sockio.h>
   61 #endif
   62 #ifdef HAVE_NET_IF_H
   63 #   include <net/if.h>
   64 #endif
   65 #ifdef HAVE_NET_IF_DL_H
   66 #   include <net/if_dl.h>
   67 #endif
   68 #ifdef HAVE_NET_IF_ARP_H
   69 #   include <net/if_arp.h>
   70 #endif
   71 #ifdef HAVE_NETINET_IN_H
   72 #   include <netinet/in.h>
   73 #endif
   74 #ifdef HAVE_ARPA_INET_H
   75 #   include <arpa/inet.h>
   76 #endif
   77 #ifdef HAVE_NETDB_H
   78 #   include <netdb.h>
   79 #endif
   80 #ifdef HAVE_IFADDRS_H
   81 #   include <ifaddrs.h>
   82 #endif
   83 
   84 #include "brutus_uuid.h"
   85 
   86 /*
   87  *  Bitmask Calculation Macros (up to 32 bit only)
   88  *  (Notice: bit positions are counted n...0, i.e. lowest bit is position 0)
   89  */
   90 
   91 /* generate a bitmask consisting of 1 bits from (and including)
   92    bit position `l' (left) to (and including) bit position `r' */
   93 #define BM_MASK(l,r)                    \
   94     ((((unsigned int)1<<(((l)-(r))+1))-1)<<(r))
   95 
   96 /* extract a value v from a word w at position `l' to `r' and return value */
   97 #define BM_GET(w,l,r)               \
   98     (((w)>>(r))&BM_MASK((l)-(r),0))
   99 
  100 /* insert a value v into a word w at position `l' to `r' and return word */
  101 #define BM_SET(w,l,r,v)             \
  102     ((w)|(((v)&BM_MASK((l)-(r),0))<<(r)))
  103 
  104 /* generate a single bit `b' (0 or 1) at bit position `n' */
  105 #define BM_BIT(n,b)             \
  106     ((b)<<(n))
  107 
  108 /* generate a quad word octet of bits (a half byte, i.e. bit positions 3 to 0) */
  109 #define BM_QUAD(b3,b2,b1,b0)                        \
  110     (BM_BIT(3,(b3))|BM_BIT(2,(b2))|BM_BIT(1,(b1))|BM_BIT(0,(b0)))
  111 
  112 /* generate an octet word of bits (a byte, i.e. bit positions 7 to 0) */
  113 #define BM_OCTET(b7,b6,b5,b4,b3,b2,b1,b0)           \
  114     ((BM_QUAD(b7,b6,b5,b4)<<4)|BM_QUAD(b3,b2,b1,b0))
  115 
  116 /* generate the value 2^n */
  117 #define BM_POW2(n)              \
  118     BM_BIT(n,1)
  119 
  120 /* shift word w k bits to the left or to the right */
  121 #define BM_SHL(w,k)             \
  122     ((w)<<(k))
  123 #define BM_SHR(w,k)             \
  124     ((w)>>(k))
  125 
  126 /* rotate word w (of bits n..0) k bits to the left or to the right */
  127 #define BM_ROL(w,n,k)                           \
  128     ((BM_SHL((w),(k))&BM_MASK(n,0))|BM_SHR(((w)&BM_MASK(n,0)),(n)-(k)))
  129 #define BM_ROR(w,n,k)                           \
  130     ((BM_SHR(((w)&BM_MASK(n,0)),(k)))|BM_SHL(((w),(n)-(k))&BM_MASK(n,0)))
  131 
  132 /* F, G, H and I are basic MD5 functions. */
  133 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  134 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  135 #define H(x, y, z) ((x) ^ (y) ^ (z))
  136 #define I(x, y, z) ((y) ^ ((x) | (~z)))
  137 
  138 /* ROTATE_LEFT rotates x left n bits. */
  139 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  140 
  141 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
  142    Rotation is separate from addition to prevent recomputation. */
  143 #define FF(a, b, c, d, x, s, ac) {              \
  144         (a) += F ((b), (c), (d)) + (x) + (guint32)(ac); \
  145         (a) = ROTATE_LEFT ((a), (s));           \
  146         (a) += (b);                 \
  147     }
  148 #define GG(a, b, c, d, x, s, ac) {              \
  149         (a) += G ((b), (c), (d)) + (x) + (guint32)(ac); \
  150         (a) = ROTATE_LEFT ((a), (s));           \
  151         (a) += (b);                 \
  152     }
  153 #define HH(a, b, c, d, x, s, ac) {              \
  154         (a) += H ((b), (c), (d)) + (x) + (guint32)(ac); \
  155         (a) = ROTATE_LEFT ((a), (s));           \
  156         (a) += (b);                 \
  157     }
  158 #define II(a, b, c, d, x, s, ac) {              \
  159         (a) += I ((b), (c), (d)) + (x) + (guint32)(ac); \
  160         (a) = ROTATE_LEFT ((a), (s));           \
  161         (a) += (b);                 \
  162     }
  163 
  164 #define UI64_BASE   256     /* 2^8 */
  165 #define UI64_DIGITS 8       /* 8*8 = 64 bit */
  166 #define UIXX_T(n) struct { unsigned char x[n]; }
  167 
  168 /* fill an ui64_t with a sequence of a particular digit */
  169 #define brutus_ui64_fill(__x, __n)          \
  170     do {                                            \
  171         int __i;                                \
  172         for (__i = 0; __i < UI64_DIGITS; __i++) \
  173             (__x).x[__i] = (__n);           \
  174     } while (0)
  175 
  176 /* encoding octet stream lengths */
  177 #define UUID_LEN_BIN  (128 /*bit*/ / 8 /*bytes*/)
  178 #define UUID_LEN_STR  (128 /*bit*/ / 4 /*nibbles*/ + 4 /*hyphens*/)
  179 
  180 #define MAC_LEN 6
  181 #define SHA1_LEN_BIN 20
  182 #define SHA1_LEN_STR 40
  183 #define SHA1HashSize 20
  184 #define MD5_LEN_BIN 16
  185 #define MD5_LEN_STR 32
  186 
  187 /* maximum number of 100ns ticks of the actual resolution of system clock
  188    (which in our case is 1us (= 1000ns) because we use gettimeofday(2) */
  189 #define UUIDS_PER_TICK 10
  190 
  191 /* time offset between UUID and Unix Epoch time according to standards.
  192    (UUID UTC base time is October 15, 1582
  193    Unix UTC base time is January  1, 1970) */
  194 #define UUID_TIMEOFFSET "01B21DD213814000"
  195 
  196 /* IEEE 802 MAC address encoding/decoding bit fields */
  197 #define IEEE_MAC_MCBIT BM_OCTET(0,0,0,0,0,0,0,1)
  198 #define IEEE_MAC_LOBIT BM_OCTET(0,0,0,0,0,0,1,0)
  199 
  200 /* IEEE 802 MAC address octet length */
  201 #define IEEE_MAC_OCTETS 6
  202 
  203 /* API return codes */
  204 typedef enum {
  205     UUID_RC_OK = 0,     /* everything ok    */
  206     UUID_RC_ARG = 1,    /* invalid argument */
  207     UUID_RC_MEM = 2,    /* out of memory    */
  208     UUID_RC_SYS = 3,    /* system error     */
  209     UUID_RC_INT = 4,    /* internal error   */
  210     UUID_RC_IMP = 5     /* not implemented  */
  211 } uuid_rc_t;
  212 
  213 /* UUID import/export formats */
  214 typedef enum {
  215     UUID_FMT_BIN = 0,   /* binary representation (import/export) */
  216     UUID_FMT_STR = 1,   /* string representation (import/export) */
  217 } uuid_fmt_t;
  218 
  219 
  220 typedef struct {
  221     unsigned char x[8]; /* x_0, ..., x_7 */
  222 } ui64_t;
  223 
  224 typedef enum {
  225     PRNG_RC_OK = 0,
  226     PRNG_RC_ARG = 1,
  227     PRNG_RC_MEM = 2,
  228     PRNG_RC_INT = 3
  229 } prng_rc_t;
  230 
  231 typedef enum {
  232     SHA1_RC_OK = 0,
  233     SHA1_RC_ARG = 1,
  234     SHA1_RC_MEM = 2,
  235     SHA1_RC_INT = 3
  236 } sha1_rc_t;
  237 
  238 /* This structure will hold context information for the SHA-1 hashing operation */
  239 typedef struct SHA1Context {
  240     guint32 Intermediate_Hash[SHA1HashSize / 4]; /* Message Digest */
  241     guint32 Length_Low;                          /* Message length in bits */
  242     guint32 Length_High;                         /* Message length in bits */
  243     gint16 Message_Block_Index;                  /* Index into message block array */
  244     guint8 Message_Block[64];                    /* 512-bit message blocks */
  245     int Computed;                                /* Is the digest computed? */
  246     int Corrupted;                               /* Is the message digest corrupted? */
  247 } SHA1Context;
  248 
  249 typedef unsigned char *POINTER;
  250 
  251 /* finalization padding */
  252 static unsigned char PADDING[64] = {
  253     0x80, 0, 0, 0, 0, 0, 0, 0, 
  254     0, 0, 0, 0, 0, 0, 0, 0, 
  255     0, 0, 0, 0, 0, 0, 0, 0, 
  256     0, 0, 0, 0, 0, 0, 0, 0, 
  257     0, 0, 0, 0, 0, 0, 0, 0, 
  258     0, 0, 0, 0, 0, 0, 0, 0, 
  259     0, 0, 0, 0, 0, 0, 0, 0, 
  260     0, 0, 0, 0, 0, 0, 0, 0
  261 };
  262 
  263 typedef enum {
  264     MD5_RC_OK = 0,
  265     MD5_RC_ARG = 1,
  266     MD5_RC_MEM = 2
  267 } md5_rc_t;
  268 
  269 /* MD5 context. */
  270 typedef struct {
  271     guint32 state[4];   /* state (ABCD) */
  272     guint32 count[2];   /* number of bits, modulo 2^64 (lsb first) */
  273     guint8 buffer[64];  /* input buffer */
  274 } MD5_CTX;
  275 
  276 typedef struct md5_st {
  277     MD5_CTX ctx;
  278 } md5_t;
  279 
  280 typedef struct sha1_st {
  281     SHA1Context ctx;
  282 } sha1_t;
  283 
  284 typedef struct prng_st {
  285     int dev;        /* system PRNG device */
  286     md5_t *md5;     /* local MD5 PRNG engine */
  287     long cnt;       /* time resolution compensation counter */
  288 } prng_t;
  289 
  290 /* UUID binary representation according to UUID standards */
  291 typedef struct {
  292     guint32 time_low;   /* bits  0-31 of time field */
  293     guint16 time_mid;   /* bits 32-47 of time field */
  294     guint16 time_hi_and_version;    /* bits 48-59 of time field plus 4 bit version */
  295     guint8 clock_seq_hi_and_reserved;   /* bits  8-13 of clock sequence field plus 2 bit variant */
  296     guint8 clock_seq_low;   /* bits  0-7  of clock sequence field */
  297     guint8 node[IEEE_MAC_OCTETS];   /* bits  0-47 of node MAC address */
  298 } uuid_obj_t;
  299 
  300 /* abstract data type (ADT) of API */
  301 typedef struct uuid_st {
  302     uuid_obj_t obj;     /* inlined UUID object */
  303     prng_t *prng;       /* RPNG sub-object */
  304     md5_t *md5;     /* MD5 sub-object */
  305     sha1_t *sha1;       /* SHA-1 sub-object */
  306     guint8 mac[IEEE_MAC_OCTETS];    /* pre-determined MAC address */
  307     struct timeval time_last;   /* last retrieved timestamp */
  308     unsigned long time_seq; /* last timestamp sequence counter */
  309 } uuid_t;
  310 
  311 /* INTERNAL: pre-defined UUID values.
  312    (defined as network byte ordered octet stream) */
  313 #define UUID_MAKE(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16) \
  314     { (guint8)(a1),  (guint8)(a2),  (guint8)(a3),  (guint8)(a4),    \
  315             (guint8)(a5),  (guint8)(a6),  (guint8)(a7),  (guint8)(a8), \
  316             (guint8)(a9),  (guint8)(a10), (guint8)(a11), (guint8)(a12), \
  317             (guint8)(a13), (guint8)(a14), (guint8)(a15), (guint8)(a16) }
  318 static struct {
  319     char *name;
  320     guint8 uuid[UUID_LEN_BIN];
  321 } uuid_value_table[] = {
  322     {
  323         "nil",     /* 00000000-0000-0000-0000-000000000000 ("Nil UUID") */
  324         UUID_MAKE(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  325               0x00, 0x00, 0x00, 0x00, 0x00,
  326               0x00, 0x00, 0x00, 0x00)}, {
  327         "ns:DNS",  /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 (see RFC 4122) */
  328         UUID_MAKE(0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11,
  329               0xd1, 0x80, 0xb4, 0x00, 0xc0,
  330               0x4f, 0xd4, 0x30, 0xc8)}, {
  331         "ns:URL",  /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 (see RFC 4122) */
  332         UUID_MAKE(0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11,
  333               0xd1, 0x80, 0xb4, 0x00, 0xc0,
  334               0x4f, 0xd4, 0x30, 0xc8)}, {
  335         "ns:OID",  /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 (see RFC 4122) */
  336         UUID_MAKE(0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11,
  337               0xd1, 0x80, 0xb4, 0x00, 0xc0,
  338               0x4f, 0xd4, 0x30, 0xc8)}, {
  339         "ns:X500", /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 (see RFC 4122) */
  340         UUID_MAKE(0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11,
  341               0xd1, 0x80, 0xb4, 0x00, 0xc0,
  342               0x4f, 0xd4, 0x30, 0xc8)}
  343 };
  344 
  345 /* Decodes input (unsigned char) into output (guint32).
  346    Assumes len is a multiple of 4. */
  347 static void
  348 Decode(guint32 * output,
  349        unsigned char *input,
  350        unsigned int len)
  351 {
  352     unsigned int i, j;
  353 
  354     for (i = 0, j = 0; j < len; i++, j += 4)
  355         output[i] = ((guint32) input[j])
  356             | (((guint32) input[j + 1]) << 8)
  357             | (((guint32) input[j + 2]) << 16)
  358             | (((guint32) input[j + 3]) << 24);
  359     return;
  360 }
  361 
  362 /* MD5 basic transformation. Transforms state based on block. */
  363 static void
  364 MD5Transform(guint32 state[],
  365          unsigned char block[])
  366 {
  367     guint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
  368 
  369     Decode(x, block, 64);
  370 
  371     /* Round 1 */
  372 #define S11 7
  373 #define S12 12
  374 #define S13 17
  375 #define S14 22
  376     FF(a, b, c, d, x[0], S11, 0xd76aa478);  /* 1 */
  377     FF(d, a, b, c, x[1], S12, 0xe8c7b756);  /* 2 */
  378     FF(c, d, a, b, x[2], S13, 0x242070db);  /* 3 */
  379     FF(b, c, d, a, x[3], S14, 0xc1bdceee);  /* 4 */
  380     FF(a, b, c, d, x[4], S11, 0xf57c0faf);  /* 5 */
  381     FF(d, a, b, c, x[5], S12, 0x4787c62a);  /* 6 */
  382     FF(c, d, a, b, x[6], S13, 0xa8304613);  /* 7 */
  383     FF(b, c, d, a, x[7], S14, 0xfd469501);  /* 8 */
  384     FF(a, b, c, d, x[8], S11, 0x698098d8);  /* 9 */
  385     FF(d, a, b, c, x[9], S12, 0x8b44f7af);  /* 10 */
  386     FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  387     FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  388     FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  389     FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  390     FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  391     FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
  392 
  393     /* Round 2 */
  394 #define S21 5
  395 #define S22 9
  396 #define S23 14
  397 #define S24 20
  398     GG(a, b, c, d, x[1], S21, 0xf61e2562);  /* 17 */
  399     GG(d, a, b, c, x[6], S22, 0xc040b340);  /* 18 */
  400     GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  401     GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);  /* 20 */
  402     GG(a, b, c, d, x[5], S21, 0xd62f105d);  /* 21 */
  403     GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */
  404     GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  405     GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);  /* 24 */
  406     GG(a, b, c, d, x[9], S21, 0x21e1cde6);  /* 25 */
  407     GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  408     GG(c, d, a, b, x[3], S23, 0xf4d50d87);  /* 27 */
  409     GG(b, c, d, a, x[8], S24, 0x455a14ed);  /* 28 */
  410     GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  411     GG(d, a, b, c, x[2], S22, 0xfcefa3f8);  /* 30 */
  412     GG(c, d, a, b, x[7], S23, 0x676f02d9);  /* 31 */
  413     GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
  414 
  415     /* Round 3 */
  416 #define S31 4
  417 #define S32 11
  418 #define S33 16
  419 #define S34 23
  420     HH(a, b, c, d, x[5], S31, 0xfffa3942);  /* 33 */
  421     HH(d, a, b, c, x[8], S32, 0x8771f681);  /* 34 */
  422     HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  423     HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  424     HH(a, b, c, d, x[1], S31, 0xa4beea44);  /* 37 */
  425     HH(d, a, b, c, x[4], S32, 0x4bdecfa9);  /* 38 */
  426     HH(c, d, a, b, x[7], S33, 0xf6bb4b60);  /* 39 */
  427     HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  428     HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  429     HH(d, a, b, c, x[0], S32, 0xeaa127fa);  /* 42 */
  430     HH(c, d, a, b, x[3], S33, 0xd4ef3085);  /* 43 */
  431     HH(b, c, d, a, x[6], S34, 0x4881d05);   /* 44 */
  432     HH(a, b, c, d, x[9], S31, 0xd9d4d039);  /* 45 */
  433     HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  434     HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  435     HH(b, c, d, a, x[2], S34, 0xc4ac5665);  /* 48 */
  436 
  437     /* Round 4 */
  438 #define S41 6
  439 #define S42 10
  440 #define S43 15
  441 #define S44 21
  442     II(a, b, c, d, x[0], S41, 0xf4292244);  /* 49 */
  443     II(d, a, b, c, x[7], S42, 0x432aff97);  /* 50 */
  444     II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  445     II(b, c, d, a, x[5], S44, 0xfc93a039);  /* 52 */
  446     II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  447     II(d, a, b, c, x[3], S42, 0x8f0ccc92);  /* 54 */
  448     II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  449     II(b, c, d, a, x[1], S44, 0x85845dd1);  /* 56 */
  450     II(a, b, c, d, x[8], S41, 0x6fa87e4f);  /* 57 */
  451     II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  452     II(c, d, a, b, x[6], S43, 0xa3014314);  /* 59 */
  453     II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  454     II(a, b, c, d, x[4], S41, 0xf7537e82);  /* 61 */
  455     II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  456     II(c, d, a, b, x[2], S43, 0x2ad7d2bb);  /* 63 */
  457     II(b, c, d, a, x[9], S44, 0xeb86d391);  /* 64 */
  458 
  459     state[0] += a;
  460     state[1] += b;
  461     state[2] += c;
  462     state[3] += d;
  463 
  464     /* Zeroize sensitive information. */
  465     memset((POINTER) x, 0, sizeof(x));
  466 }
  467 
  468 /* Encodes input (guint32) into output (unsigned char).
  469    Assumes len is a multiple of 4. */
  470 static void
  471 Encode(unsigned char *output,
  472        guint32 * input,
  473        unsigned int len)
  474 {
  475     unsigned int i, j;
  476 
  477     for (i = 0, j = 0; j < len; i++, j += 4) {
  478         output[j] = (unsigned char) (input[i] & 0xff);
  479         output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
  480         output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
  481         output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
  482     }
  483     return;
  484 }
  485 
  486 static void
  487 MD5Init(MD5_CTX * context)
  488 {
  489     context->count[0] = context->count[1] = 0;
  490 
  491     /* Load magic initialization constants. */
  492     context->state[0] = 0x67452301;
  493     context->state[1] = 0xefcdab89;
  494     context->state[2] = 0x98badcfe;
  495     context->state[3] = 0x10325476;
  496     return;
  497 }
  498 
  499 /* MD5 block update operation. Continues an MD5 message-digest
  500    operation, processing another message block, and updating the
  501    context. */
  502 static void
  503 MD5Update(MD5_CTX * context,    /* context */
  504       unsigned char *input, /* input block */
  505       unsigned int inputLen)
  506 {               /* length of input block */
  507     unsigned int i, idx, partLen;
  508 
  509     /* Compute number of bytes mod 64 */
  510     idx = (unsigned int) ((context->count[0] >> 3) & 0x3F);
  511 
  512     /* Update number of bits */
  513     if ((context->count[0] += ((guint32) inputLen << 3)) < ((guint32) inputLen << 3))
  514         context->count[1]++;
  515     context->count[1] += ((guint32) inputLen >> 29);
  516 
  517     partLen = (unsigned int) 64 - idx;
  518 
  519     /* Transform as many times as possible.  */
  520     if (inputLen >= partLen) {
  521         memcpy((POINTER) & context->buffer[idx], (POINTER) input, (size_t) partLen);
  522         MD5Transform(context->state, context->buffer);
  523         for (i = partLen; i + 63 < inputLen; i += 64)
  524             MD5Transform(context->state, &input[i]);
  525         idx = 0;
  526     } else
  527         i = 0;
  528 
  529     /* Buffer remaining input */
  530     memcpy((POINTER) & context->buffer[idx], (POINTER) & input[i], (size_t) (inputLen - i));
  531 }
  532 
  533 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
  534    the message digest and zeroizing the context. */
  535 static void
  536 MD5Final(unsigned char digest[], /* message digest */
  537      MD5_CTX * context)      /* context */
  538 {               
  539     unsigned char bits[8];
  540     unsigned int idx, padLen;
  541 
  542     /* Save number of bits */
  543     Encode(bits, context->count, 8);
  544 
  545     /* Pad out to 56 mod 64. */
  546     idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
  547     padLen = (idx < 56) ? ((unsigned int) 56 - idx) : ((unsigned int) 120 - idx);
  548     MD5Update(context, PADDING, padLen);
  549 
  550     /* Append length (before padding) */
  551     MD5Update(context, bits, 8);
  552 
  553     /* Store state in digest */
  554     Encode(digest, context->state, 16);
  555 
  556     /* Zeroize sensitive information. */
  557     memset((POINTER) context, 0, sizeof(*context));
  558 }
  559 
  560 static md5_rc_t
  561 brutus_md5_create(md5_t ** md5)
  562 {
  563     if (md5 == NULL)
  564         return MD5_RC_ARG;
  565     if ((*md5 = (md5_t *) malloc(sizeof(md5_t))) == NULL)
  566         return MD5_RC_MEM;
  567     MD5Init(&((*md5)->ctx));
  568 
  569     return MD5_RC_OK;
  570 }
  571 
  572 static md5_rc_t
  573 brutus_md5_update(md5_t * md5,
  574           const void *data_ptr,
  575           size_t data_len)
  576 {
  577     if (md5 == NULL)
  578         return MD5_RC_ARG;
  579     MD5Update(&(md5->ctx), (unsigned char *) data_ptr,
  580           (unsigned int) data_len);
  581     return MD5_RC_OK;
  582 }
  583 
  584 static md5_rc_t
  585 brutus_md5_store(md5_t * md5,
  586          void **data_ptr,
  587          size_t * data_len)
  588 {
  589     MD5_CTX ctx;
  590 
  591     if (md5 == NULL || data_ptr == NULL)
  592         return MD5_RC_ARG;
  593     if (*data_ptr == NULL) {
  594         *data_ptr = malloc(MD5_LEN_BIN);
  595 
  596         if (NULL == *data_ptr)
  597             return MD5_RC_MEM;
  598         if (data_len != NULL)
  599             *data_len = MD5_LEN_BIN;
  600     } else {
  601         if (data_len != NULL) {
  602             if (*data_len < MD5_LEN_BIN)
  603                 return MD5_RC_MEM;
  604             *data_len = MD5_LEN_BIN;
  605         }
  606     }
  607     memcpy((void *) (&ctx), (void *) (&(md5->ctx)), sizeof(MD5_CTX));
  608     MD5Final((unsigned char *) (*data_ptr), &(ctx));
  609 
  610     return MD5_RC_OK;
  611 }
  612 
  613 static md5_rc_t
  614 brutus_md5_destroy(md5_t * md5)
  615 {
  616     if (md5 == NULL)
  617         return MD5_RC_ARG;
  618     free(md5);
  619 
  620     return MD5_RC_OK;
  621 }
  622 
  623 /*
  624  *  This function will initialize the SHA1Context in preparation for
  625  *  computing a new SHA1 message digest.
  626  */
  627 static int
  628 brutus_SHA1Reset(SHA1Context * context)
  629 {
  630     if (context == NULL)
  631         return 1;
  632 
  633     context->Length_Low = 0;
  634     context->Length_High = 0;
  635     context->Message_Block_Index = 0;
  636 
  637     context->Intermediate_Hash[0] = 0x67452301;
  638     context->Intermediate_Hash[1] = 0xEFCDAB89;
  639     context->Intermediate_Hash[2] = 0x98BADCFE;
  640     context->Intermediate_Hash[3] = 0x10325476;
  641     context->Intermediate_Hash[4] = 0xC3D2E1F0;
  642 
  643     context->Computed = 0;
  644     context->Corrupted = 0;
  645 
  646     return 0;
  647 }
  648 
  649 static sha1_rc_t
  650 brutus_sha1_create(sha1_t ** sha1)
  651 {
  652     if (sha1 == NULL)
  653         return SHA1_RC_ARG;
  654     if ((*sha1 = (sha1_t *) malloc(sizeof(sha1_t))) == NULL)
  655         return SHA1_RC_MEM;
  656     if (brutus_SHA1Reset(&((*sha1)->ctx)))
  657         return SHA1_RC_INT;
  658 
  659     return SHA1_RC_OK;
  660 }
  661 
  662 static sha1_rc_t
  663 brutus_sha1_destroy(sha1_t * sha1)
  664 {
  665     if (sha1 == NULL)
  666         return SHA1_RC_ARG;
  667     free(sha1);
  668 
  669     return SHA1_RC_OK;
  670 }
  671 
  672 
  673 static prng_rc_t
  674 brutus_prng_create(prng_t ** prng)
  675 {
  676     int fd = -1;
  677     struct timeval tv;
  678     pid_t pid;
  679     unsigned int i;
  680 
  681     /* sanity check argument(s) */
  682     if (prng == NULL)
  683         return PRNG_RC_ARG;
  684 
  685     /* allocate object */
  686     if ((*prng = (prng_t *) malloc(sizeof(prng_t))) == NULL)
  687         return PRNG_RC_MEM;
  688 
  689     /* try to open the system PRNG device */
  690     (*prng)->dev = -1;
  691     if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
  692         fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
  693     if (fd != -1) {
  694         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
  695         (*prng)->dev = fd;
  696     }
  697 
  698     /* initialize MD5 engine */
  699     if (brutus_md5_create(&((*prng)->md5)) != MD5_RC_OK) {
  700         free(*prng);
  701         return PRNG_RC_INT;
  702     }
  703 
  704     /* initialize time resolution compensation counter */
  705     (*prng)->cnt = 0;
  706 
  707     /* seed the C library PRNG once */
  708     (void) gettimeofday(&tv, NULL);
  709     pid = getpid();
  710     srand((unsigned int) (((unsigned int) pid << 16)
  711                   ^ (unsigned int) pid
  712                   ^ (unsigned int) tv.tv_sec
  713                   ^ (unsigned int) tv.tv_usec));
  714     for (i = (unsigned int) ((tv.tv_sec ^ tv.tv_usec) & 0x1F); i > 0; i--)
  715         (void) rand();
  716 
  717     return PRNG_RC_OK;
  718 }
  719 
  720 static prng_rc_t
  721 brutus_prng_data(prng_t * prng,
  722          void *data_ptr,
  723          size_t data_len)
  724 {
  725     size_t n;
  726     unsigned char *p;
  727     struct {
  728         struct timeval tv;
  729         long cnt;
  730         int rnd;
  731     } entropy;
  732     unsigned char md5_buf[MD5_LEN_BIN] = { 0 };
  733     void *md5_ptr;
  734     size_t md5_len;
  735     int retries;
  736     int i;
  737 
  738     /* sanity check argument(s) */
  739     if (prng == NULL || data_len == 0)
  740         return PRNG_RC_ARG;
  741 
  742     /* prepare for generation */
  743     p = (unsigned char *) data_ptr;
  744     n = data_len;
  745 
  746     /* approach 1: try to gather data via stronger system PRNG device */
  747     if (prng->dev != -1) {
  748         retries = 0;
  749         while (n > 0) {
  750             i = (int) read(prng->dev, (void *) p, n);
  751             if (i <= 0) {
  752                 if (retries++ > 16)
  753                     break;
  754                 continue;
  755             }
  756             retries = 0;
  757             n -= (unsigned int) i;
  758             p += (unsigned int) i;
  759         }
  760     }
  761 
  762     /* approach 2: try to gather data via weaker libc PRNG API. */
  763     while (n > 0) {
  764         /* gather new entropy */
  765         (void) gettimeofday(&(entropy.tv), NULL);   /* source: libc time */
  766         entropy.rnd = rand();   /* source: libc PRNG */
  767         entropy.cnt = prng->cnt++;  /* source: local counter */
  768 
  769         /* pass entropy into MD5 engine */
  770         if (brutus_md5_update(prng->md5, (void *) &entropy, sizeof(entropy)) != MD5_RC_OK)
  771             return PRNG_RC_INT;
  772 
  773         /* store MD5 engine state as PRN output */
  774         md5_ptr = (void*)md5_buf;
  775         md5_len = sizeof(md5_buf);
  776         if (brutus_md5_store(prng->md5, &md5_ptr, &md5_len) != MD5_RC_OK)
  777             return PRNG_RC_INT;
  778         for (i = 0; i < MD5_LEN_BIN && n > 0; i++, n--)
  779             *p++ ^= md5_buf[i]; /* intentionally no assignment because arbitrary
  780                            caller buffer content is leveraged, too */
  781     }
  782 
  783     return PRNG_RC_OK;
  784 }
  785 
  786 static prng_rc_t
  787 brutus_prng_destroy(prng_t * prng)
  788 {
  789     /* sanity check argument(s) */
  790     if (prng == NULL)
  791         return PRNG_RC_ARG;
  792 
  793     /* close PRNG device */
  794     if (prng->dev != -1)
  795         (void) close(prng->dev);
  796 
  797     /* destroy MD5 engine */
  798     (void) brutus_md5_destroy(prng->md5);
  799 
  800     /* free object */
  801     free(prng);
  802 
  803     return PRNG_RC_OK;
  804 }
  805 
  806 /* return the Media Access Control (MAC) address of
  807    the FIRST network interface card (NIC) */
  808 static int
  809 brutus_mac_address(unsigned char *data_ptr,
  810            size_t data_len)
  811 {
  812     /* sanity check arguments */
  813     if (data_ptr == NULL || data_len < MAC_LEN)
  814         return FALSE;
  815 
  816 #if defined(HAVE_IFADDRS_H) && defined(HAVE_NET_IF_DL_H) && defined(HAVE_GETIFADDRS)
  817     /* use getifaddrs(3) on BSD class platforms (xxxBSD, MacOS X, etc) */
  818     {
  819         struct ifaddrs *ifap;
  820         struct ifaddrs *ifap_head;
  821         const struct sockaddr_dl *sdl;
  822         unsigned char *ucp;
  823         int i;
  824 
  825         if (getifaddrs(&ifap_head) < 0)
  826             return FALSE;
  827         for (ifap = ifap_head; ifap != NULL; ifap = ifap->ifa_next) {
  828             if (ifap->ifa_addr != NULL && ifap->ifa_addr->sa_family == AF_LINK) {
  829                 sdl = (const struct sockaddr_dl *) (void *) ifap->ifa_addr;
  830                 ucp = (unsigned char *) (sdl->sdl_data + sdl->sdl_nlen);
  831                 if (sdl->sdl_alen > 0) {
  832                     for (i = 0; i < MAC_LEN && i < sdl->sdl_alen; i++, ucp++)
  833                         data_ptr[i] = (unsigned char) (*ucp & 0xff);
  834                     freeifaddrs(ifap_head);
  835 
  836                     return TRUE;
  837                 }
  838             }
  839         }
  840         freeifaddrs(ifap_head);
  841     }
  842 #endif
  843 
  844 #if defined(HAVE_NET_IF_H) && defined(SIOCGIFHWADDR)
  845     /* use SIOCGIFHWADDR ioctl(2) on Linux class platforms */
  846     {
  847         struct ifreq ifr;
  848         struct sockaddr *sa;
  849         int s;
  850         int i;
  851 
  852         if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  853             return FALSE;
  854         sprintf(ifr.ifr_name, "eth0");
  855         if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
  856             close(s);
  857             return FALSE;
  858         }
  859         sa = (struct sockaddr *) &ifr.ifr_addr;
  860         for (i = 0; i < MAC_LEN; i++)
  861             data_ptr[i] = (unsigned char) (sa->sa_data[i] & 0xff);
  862         close(s);
  863 
  864         return TRUE;
  865     }
  866 #endif
  867 
  868 #if defined(SIOCGARP)
  869     /* use SIOCGARP ioctl(2) on SVR4 class platforms (Solaris, etc) */
  870     {
  871         char hostname[MAXHOSTNAMELEN];
  872         struct hostent *he;
  873         struct arpreq ar;
  874         struct sockaddr_in *sa;
  875         int s;
  876         int i;
  877 
  878         if (gethostname(hostname, sizeof(hostname)) < 0)
  879             return FALSE;
  880         if ((he = gethostbyname(hostname)) == NULL)
  881             return FALSE;
  882         if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  883             return FALSE;
  884         memset(&ar, 0, sizeof(ar));
  885         sa = (struct sockaddr_in *) ((void *) &(ar.arp_pa));
  886         sa->sin_family = AF_INET;
  887         memcpy(&(sa->sin_addr), *(he->h_addr_list), sizeof(struct in_addr));
  888         if (ioctl(s, SIOCGARP, &ar) < 0) {
  889             close(s);
  890             return FALSE;
  891         }
  892         close(s);
  893         if (!(ar.arp_flags & ATF_COM))
  894             return FALSE;
  895         for (i = 0; i < MAC_LEN; i++)
  896             data_ptr[i] = (unsigned char) (ar.arp_ha.sa_data[i] & 0xff);
  897 
  898         return TRUE;
  899     }
  900 #endif
  901 
  902     return FALSE;
  903 }
  904 
  905 /* convert ISO-C "unsigned long" into internal format */
  906 static ui64_t
  907 brutus_ui64_n2i(unsigned long n)
  908 {
  909     ui64_t z;
  910     int i;
  911 
  912     i = 0;
  913     do {
  914         z.x[i++] = (n % UI64_BASE);
  915     } while ((n /= UI64_BASE) > 0 && i < UI64_DIGITS);
  916 
  917     for (; i < UI64_DIGITS; i++)
  918         z.x[i] = 0;
  919 
  920     return z;
  921 }
  922 
  923 /* convert internal format into ISO-C "unsigned long";
  924    truncates if sizeof(unsigned long) is less than UI64_DIGITS! */
  925 static unsigned long
  926 brutus_ui64_i2n(ui64_t x)
  927 {
  928     unsigned long n;
  929     int i;
  930 
  931     n = 0;
  932     i = (int) sizeof(n);
  933 
  934     if (i > UI64_DIGITS)
  935         i = UI64_DIGITS;
  936 
  937     while (--i >= 0) {
  938         n = (n * UI64_BASE) + x.x[i];
  939     }
  940 
  941     return n;
  942 }
  943 
  944 static ui64_t
  945 brutus_ui64_muln(ui64_t x,
  946          int y,
  947          int *ov)
  948 {
  949     ui64_t z;
  950     int carry;
  951     int i;
  952 
  953     carry = 0;
  954     for (i = 0; i < UI64_DIGITS; i++) {
  955         carry += (x.x[i] * y);
  956         z.x[i] = (carry % UI64_BASE);
  957         carry /= UI64_BASE;
  958     }
  959     if (ov != NULL)
  960         *ov = carry;
  961     return z;
  962 }
  963 
  964 /* addition of an ui64_t and a single digit */
  965 static ui64_t
  966 brutus_ui64_addn(ui64_t x,
  967          int y,
  968          int *ov)
  969 {
  970     ui64_t z;
  971     int i;
  972 
  973     for (i = 0; i < UI64_DIGITS; i++) {
  974         y += x.x[i];
  975         z.x[i] = (y % UI64_BASE);
  976         y /= UI64_BASE;
  977     }
  978 
  979     if (ov != NULL)
  980         *ov = y;
  981 
  982     return z;
  983 }
  984 
  985 /* convert string representation of arbitrary base into internal format */
  986 static ui64_t
  987 brutus_ui64_s2i(const char *str,
  988         char **end,
  989         int base)
  990 {
  991     ui64_t z;
  992     const char *cp;
  993     int carry;
  994     static char map[] = {
  995         0, 1, 2, 3, 4, 5, 6, 7, 8, 9,   /* 0...9 */
  996         36, 36, 36, 36, 36, 36, 36, /* illegal chars */
  997         10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, /* A...M */
  998         23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, /* N...Z */
  999         36, 36, 36, 36, 36, 36, /* illegal chars */
 1000         10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, /* a...m */
 1001         23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35  /* m...z */
 1002     };
 1003 
 1004     brutus_ui64_fill(z, 0);
 1005     if (str == NULL || (base < 2 || base > 36))
 1006         return z;
 1007     cp = str;
 1008     while (*cp != '\0' && isspace((int) (*cp)))
 1009         cp++;
 1010     while (*cp != '\0' && isalnum((int) (*cp))
 1011            && map[(int) (*cp) - '0'] < base) {
 1012         z = brutus_ui64_muln(z, base, &carry);
 1013         if (carry)
 1014             break;
 1015         z = brutus_ui64_addn(z, map[(int) (*cp) - '0'], &carry);
 1016         if (carry)
 1017             break;
 1018         cp++;
 1019     }
 1020     if (end != NULL)
 1021         *end = (char *) cp;
 1022 
 1023     return z;
 1024 }
 1025 
 1026 /* addition of two ui64_t */
 1027 static ui64_t
 1028 brutus_ui64_add(ui64_t x,
 1029         ui64_t y,
 1030         ui64_t * ov)
 1031 {
 1032     ui64_t z;
 1033     int carry;
 1034     int i;
 1035 
 1036     carry = 0;
 1037     for (i = 0; i < UI64_DIGITS; i++) {
 1038         carry += (x.x[i] + y.x[i]);
 1039         z.x[i] = (carry % UI64_BASE);
 1040         carry /= UI64_BASE;
 1041     }
 1042 
 1043     if (ov != NULL)
 1044         *ov = brutus_ui64_n2i((unsigned long) carry);
 1045 
 1046     return z;
 1047 }
 1048 
 1049 /* the value zero */
 1050 static ui64_t
 1051 brutus_ui64_zero(void)
 1052 {
 1053     ui64_t z;
 1054 
 1055     brutus_ui64_fill(z, 0);
 1056 
 1057     return z;
 1058 }
 1059 
 1060 static ui64_t
 1061 brutus_ui64_rol(ui64_t x,
 1062         int s,
 1063         ui64_t * ov)
 1064 {
 1065     UIXX_T(UI64_DIGITS + UI64_DIGITS) zx;
 1066     ui64_t z;
 1067     int i;
 1068     int carry;
 1069 
 1070     if (s <= 0) {
 1071         /* no shift at all */
 1072         if (ov != NULL)
 1073             *ov = brutus_ui64_zero();
 1074         return x;
 1075     } else if (s > 64) {
 1076         /* too large shift */
 1077         if (ov != NULL)
 1078             *ov = brutus_ui64_zero();
 1079         return brutus_ui64_zero();
 1080     } else if (s == 64) {
 1081         /* maximum shift */
 1082         if (ov != NULL)
 1083             *ov = x;
 1084         return brutus_ui64_zero();
 1085     } else {        /* regular shift */
 1086         /* shift (logically) left by s/8 bytes */
 1087         for (i = 0; i < UI64_DIGITS + UI64_DIGITS; i++)
 1088             zx.x[i] = 0;
 1089         for (i = 0; i < UI64_DIGITS; i++)
 1090             zx.x[i + (s / 8)] = x.x[i];
 1091         /* shift (logically) left by remaining s%8 bits */
 1092         s %= 8;
 1093         if (s > 0) {
 1094             carry = 0;
 1095             for (i = 0; i < UI64_DIGITS + UI64_DIGITS; i++) {
 1096                 carry += (zx.x[i] * (1 << s));
 1097                 zx.x[i] = (carry % UI64_BASE);
 1098                 carry /= UI64_BASE;
 1099             }
 1100         }
 1101         memcpy(z.x, zx.x, UI64_DIGITS);
 1102         if (ov != NULL)
 1103             memcpy((*ov).x, &zx.x[UI64_DIGITS], UI64_DIGITS);
 1104     }
 1105 
 1106     return z;
 1107 }
 1108 
 1109 /* destroy UUID object */
 1110 static uuid_rc_t
 1111 uuid_destroy(uuid_t * uuid)
 1112 {
 1113     /* argument sanity check */
 1114     if (uuid == NULL)
 1115         return UUID_RC_ARG;
 1116 
 1117     /* destroy PRNG, MD5 and SHA-1 sub-objects */
 1118     (void) brutus_prng_destroy(uuid->prng);
 1119     (void) brutus_md5_destroy(uuid->md5);
 1120     (void) brutus_sha1_destroy(uuid->sha1);
 1121 
 1122     /* free UUID object */
 1123     free(uuid);
 1124 
 1125     return UUID_RC_OK;
 1126 }
 1127 
 1128 /* INTERNAL: unpack UUID binary presentation into UUID object
 1129    (allows in-place operation for internal efficiency!) */
 1130 static uuid_rc_t
 1131 uuid_import_bin(uuid_t * uuid,
 1132         const void *data_ptr,
 1133         size_t data_len)
 1134 {
 1135     const guint8 *in;
 1136     guint32 tmp32;
 1137     guint16 tmp16;
 1138     unsigned int i;
 1139 
 1140     /* sanity check argument(s) */
 1141     if (uuid == NULL || data_ptr == NULL || data_len < UUID_LEN_BIN)
 1142         return UUID_RC_ARG;
 1143 
 1144     /* treat input data buffer as octet stream */
 1145     in = (const guint8 *) data_ptr;
 1146 
 1147     /* unpack "time_low" field */
 1148     tmp32 = (guint32) (*in++);
 1149     tmp32 = (tmp32 << 8) | (guint32) (*in++);
 1150     tmp32 = (tmp32 << 8) | (guint32) (*in++);
 1151     tmp32 = (tmp32 << 8) | (guint32) (*in++);
 1152     uuid->obj.time_low = tmp32;
 1153 
 1154     /* unpack "time_mid" field */
 1155     tmp16 = (guint16) (*in++);
 1156     tmp16 = (guint16) (tmp16 << 8) | (guint16) (*in++);
 1157     uuid->obj.time_mid = tmp16;
 1158 
 1159     /* unpack "time_hi_and_version" field */
 1160     tmp16 = (guint16) * in++;
 1161     tmp16 = (guint16) (tmp16 << 8) | (guint16) (*in++);
 1162     uuid->obj.time_hi_and_version = tmp16;
 1163 
 1164     /* unpack "clock_seq_hi_and_reserved" field */
 1165     uuid->obj.clock_seq_hi_and_reserved = *in++;
 1166 
 1167     /* unpack "clock_seq_low" field */
 1168     uuid->obj.clock_seq_low = *in++;
 1169 
 1170     /* unpack "node" field */
 1171     for (i = 0; i < (unsigned int) sizeof(uuid->obj.node); i++)
 1172         uuid->obj.node[i] = *in++;
 1173 
 1174     return UUID_RC_OK;
 1175 }
 1176 
 1177 
 1178 /* INTERNAL: check for valid UUID string representation syntax */
 1179 static int
 1180 uuid_isstr(const char *str,
 1181        size_t str_len)
 1182 {
 1183     int i;
 1184     const char *cp;
 1185 
 1186     /* example reference:
 1187        f81d4fae-7dec-11d0-a765-00a0c91e6bf6
 1188        012345678901234567890123456789012345
 1189        0         1         2         3       */
 1190     if (str == NULL)
 1191         return FALSE;
 1192     if (str_len == 0)
 1193         str_len = strlen(str);
 1194     if (str_len < UUID_LEN_STR)
 1195         return FALSE;
 1196     for (i = 0, cp = str; i < UUID_LEN_STR; i++, cp++) {
 1197         if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
 1198             if (*cp == '-')
 1199                 continue;
 1200             else
 1201                 return FALSE;
 1202         }
 1203         if (!isxdigit((int) (*cp)))
 1204             return FALSE;
 1205     }
 1206 
 1207     return TRUE;
 1208 }
 1209 
 1210 /* INTERNAL: import UUID object from string representation */
 1211 static uuid_rc_t
 1212 uuid_import_str(uuid_t * uuid,
 1213         const void *data_ptr,
 1214         size_t data_len)
 1215 {
 1216     guint16 tmp16;
 1217     const char *cp;
 1218     char hexbuf[3];
 1219     const char *str;
 1220     unsigned int i;
 1221 
 1222     /* sanity check argument(s) */
 1223     if (uuid == NULL || data_ptr == NULL || data_len < UUID_LEN_STR)
 1224         return UUID_RC_ARG;
 1225 
 1226     /* check for correct UUID string representation syntax */
 1227     str = (const char *) data_ptr;
 1228     if (!uuid_isstr(str, 0))
 1229         return UUID_RC_ARG;
 1230 
 1231     /* parse hex values of "time" parts */
 1232     uuid->obj.time_low = (guint32) strtoul(str, NULL, 16);
 1233     uuid->obj.time_mid = (guint16) strtoul(str + 9, NULL, 16);
 1234     uuid->obj.time_hi_and_version = (guint16) strtoul(str + 14, NULL, 16);
 1235 
 1236     /* parse hex values of "clock" parts */
 1237     tmp16 = (guint16) strtoul(str + 19, NULL, 16);
 1238     uuid->obj.clock_seq_low = (guint8) (tmp16 & 0xff);
 1239     tmp16 >>= 8;
 1240     uuid->obj.clock_seq_hi_and_reserved = (guint8) (tmp16 & 0xff);
 1241 
 1242     /* parse hex values of "node" part */
 1243     cp = str + 24;
 1244     hexbuf[2] = '\0';
 1245     for (i = 0; i < (unsigned int) sizeof(uuid->obj.node); i++) {
 1246         hexbuf[0] = *cp++;
 1247         hexbuf[1] = *cp++;
 1248         uuid->obj.node[i] = (guint8) strtoul(hexbuf, NULL, 16);
 1249     }
 1250 
 1251     return UUID_RC_OK;
 1252 }
 1253 
 1254 /* INTERNAL: export UUID object to string representation */
 1255 static uuid_rc_t
 1256 uuid_export_str(const uuid_t * uuid,
 1257         uuid_str_t uuid_str)
 1258 {
 1259     /* sanity check argument(s) */
 1260     if (uuid == NULL)
 1261         return UUID_RC_ARG;
 1262 
 1263     /* format UUID into string representation */
 1264     if (g_snprintf(uuid_str,
 1265                UUID_LEN_STR + 1,
 1266                "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
 1267                (unsigned long) uuid->obj.time_low,
 1268                (unsigned int) uuid->obj.time_mid,
 1269                (unsigned int) uuid->obj.time_hi_and_version,
 1270                (unsigned int) uuid->obj.clock_seq_hi_and_reserved,
 1271                (unsigned int) uuid->obj.clock_seq_low,
 1272                (unsigned int) uuid->obj.node[0],
 1273                (unsigned int) uuid->obj.node[1],
 1274                (unsigned int) uuid->obj.node[2],
 1275                (unsigned int) uuid->obj.node[3],
 1276                (unsigned int) uuid->obj.node[4],
 1277                (unsigned int) uuid->obj.node[5]) != UUID_LEN_STR) {
 1278         return UUID_RC_INT;
 1279     }
 1280 
 1281     return UUID_RC_OK;
 1282 }
 1283 
 1284 /* UUID importing */
 1285 static uuid_rc_t
 1286 uuid_import(uuid_t * uuid,
 1287         uuid_fmt_t fmt,
 1288         const void *data_ptr,
 1289         size_t data_len)
 1290 {
 1291     uuid_rc_t rc;
 1292 
 1293     /* sanity check argument(s) */
 1294     if (uuid == NULL || data_ptr == NULL)
 1295         return UUID_RC_ARG;
 1296 
 1297     /* dispatch into format-specific functions */
 1298     switch (fmt) {
 1299     case UUID_FMT_BIN:
 1300         rc = uuid_import_bin(uuid, data_ptr, data_len);
 1301         break;
 1302     case UUID_FMT_STR:
 1303         rc = uuid_import_str(uuid, data_ptr, data_len);
 1304         break;
 1305     default:
 1306         rc = UUID_RC_ARG;
 1307     }
 1308 
 1309     return rc;
 1310 }
 1311 
 1312 /* load UUID object with pre-defined value */
 1313 static uuid_rc_t
 1314 uuid_load(uuid_t * uuid,
 1315       const char *name)
 1316 {
 1317     guint8 *uuid_octets;
 1318     uuid_rc_t rc;
 1319     unsigned int i;
 1320 
 1321     /* sanity check argument(s) */
 1322     if (uuid == NULL || name == NULL)
 1323         return UUID_RC_ARG;
 1324 
 1325     /* search for UUID in table */
 1326     uuid_octets = NULL;
 1327     for (i = 0; i < (unsigned int) sizeof(uuid_value_table) / sizeof(uuid_value_table[0]); i++) {
 1328         if (strcmp(uuid_value_table[i].name, name) == 0) {
 1329             uuid_octets = uuid_value_table[i].uuid;
 1330             break;
 1331         }
 1332     }
 1333     if (uuid_octets == NULL)
 1334         return UUID_RC_ARG;
 1335 
 1336     /* import value into UUID object */
 1337     if ((rc = uuid_import(uuid, UUID_FMT_BIN, uuid_octets, UUID_LEN_BIN)) != UUID_RC_OK)
 1338         return rc;
 1339 
 1340     return UUID_RC_OK;
 1341 }
 1342 
 1343 
 1344 /* INTERNAL: brand UUID with version and variant */
 1345 static void
 1346 uuid_brand(uuid_t * uuid,
 1347        unsigned int version)
 1348 {
 1349     /* set version (as given) */
 1350     uuid->obj.time_hi_and_version &= BM_MASK(11, 0);
 1351     uuid->obj.time_hi_and_version |= (guint16) BM_SHL(version, 12);
 1352 
 1353     /* set variant (always DCE 1.1 only) */
 1354     uuid->obj.clock_seq_hi_and_reserved &= BM_MASK(5, 0);
 1355     uuid->obj.clock_seq_hi_and_reserved |= BM_SHL(0x02, 6);
 1356 
 1357     return;
 1358 }
 1359 
 1360 /* INTERNAL: generate UUID version 1: time, clock and node based */
 1361 static uuid_rc_t
 1362 uuid_make(uuid_t * uuid)
 1363 {
 1364     struct timeval time_now;
 1365 #ifdef HAVE_NANOSLEEP
 1366     struct timespec ts;
 1367 #else
 1368     struct timeval tv;
 1369 #endif
 1370     ui64_t t;
 1371     ui64_t offset;
 1372     ui64_t ov;
 1373     guint16 clck;
 1374 
 1375     /*
 1376      *  GENERATE TIME
 1377      */
 1378 
 1379     /* determine current system time and sequence counter */
 1380     for (;;) {
 1381         /* determine current system time */
 1382         if (gettimeofday(&time_now, NULL) == -1)
 1383             return UUID_RC_SYS;
 1384 
 1385         /* check whether system time changed since last retrieve */
 1386         if (!(time_now.tv_sec == uuid->time_last.tv_sec
 1387               && time_now.tv_usec == uuid->time_last.tv_usec)) {
 1388             /* reset time sequence counter and continue */
 1389             uuid->time_seq = 0;
 1390             break;
 1391         }
 1392 
 1393         /* until we are out of UUIDs per tick, increment
 1394            the time/tick sequence counter and continue */
 1395         if (uuid->time_seq < UUIDS_PER_TICK) {
 1396             uuid->time_seq++;
 1397             break;
 1398         }
 1399 
 1400         /* stall the UUID generation until the system clock (which
 1401            has a gettimeofday(2) resolution of 1us) catches up */
 1402 #ifdef HAVE_NANOSLEEP
 1403         /* sleep for 500ns (1/2us) */
 1404         ts.tv_sec = 0;
 1405         ts.tv_nsec = 500;
 1406         nanosleep(&ts, NULL);
 1407 #else
 1408         /* sleep for 1000ns (1us) */
 1409         tv.tv_sec = 0;
 1410         tv.tv_usec = 1;
 1411         select(0, NULL, NULL, NULL, &tv);
 1412 #endif
 1413     }
 1414 
 1415     /* convert from timeval (sec,usec) to OSSP ui64 (100*nsec) format */
 1416     t = brutus_ui64_n2i((unsigned long) time_now.tv_sec);
 1417     t = brutus_ui64_muln(t, 1000000, NULL);
 1418     t = brutus_ui64_addn(t, (int) time_now.tv_usec, NULL);
 1419     t = brutus_ui64_muln(t, 10, NULL);
 1420 
 1421     /* adjust for offset between UUID and Unix Epoch time */
 1422     offset = brutus_ui64_s2i(UUID_TIMEOFFSET, NULL, 16);
 1423     t = brutus_ui64_add(t, offset, NULL);
 1424 
 1425     /* compensate for low resolution system clock by adding
 1426        the time/tick sequence counter */
 1427     if (uuid->time_seq > 0)
 1428         t = brutus_ui64_addn(t, (int) uuid->time_seq, NULL);
 1429 
 1430     /* store the 60 LSB of the time in the UUID */
 1431     t = brutus_ui64_rol(t, 16, &ov);
 1432     uuid->obj.time_hi_and_version = (guint16) (brutus_ui64_i2n(ov) & 0x00000fff);   /* 12 of 16 bit only! */
 1433     t = brutus_ui64_rol(t, 16, &ov);
 1434     uuid->obj.time_mid = (guint16) (brutus_ui64_i2n(ov) & 0x0000ffff);  /* all 16 bit */
 1435     t = brutus_ui64_rol(t, 32, &ov);
 1436     uuid->obj.time_low = (guint32) (brutus_ui64_i2n(ov) & 0xffffffff);  /* all 32 bit */
 1437 
 1438     /*
 1439      *  GENERATE CLOCK
 1440      */
 1441 
 1442     /* retrieve current clock sequence */
 1443     clck = ((uuid->obj.clock_seq_hi_and_reserved & BM_MASK(5, 0)) << 8) + uuid->obj.clock_seq_low;
 1444 
 1445     /* generate new random clock sequence (initially or if the
 1446        time has stepped backwards) or else just increase it */
 1447     if (!clck
 1448         || (time_now.tv_sec < uuid->time_last.tv_sec
 1449         || (time_now.tv_sec == uuid->time_last.tv_sec
 1450             && time_now.tv_usec < uuid->time_last.tv_usec))) {
 1451         if (brutus_prng_data(uuid->prng, (void *) &clck, sizeof(clck)) != PRNG_RC_OK)
 1452             return UUID_RC_INT;
 1453     } else
 1454         clck++;
 1455     clck %= BM_POW2(14);
 1456 
 1457     /* store back new clock sequence */
 1458     uuid->obj.clock_seq_hi_and_reserved = (uuid->obj.clock_seq_hi_and_reserved & BM_MASK(7, 6)) | (guint8) ((clck >> 8) & 0xff);
 1459     uuid->obj.clock_seq_low = (guint8) (clck & 0xff);
 1460 
 1461     /*
 1462      *  GENERATE NODE
 1463      */
 1464 
 1465     memcpy(uuid->obj.node, uuid->mac, sizeof(uuid->mac));
 1466 
 1467     /*
 1468      *  FINISH
 1469      */
 1470 
 1471     /* remember current system time for next iteration */
 1472     uuid->time_last.tv_sec = time_now.tv_sec;
 1473     uuid->time_last.tv_usec = time_now.tv_usec;
 1474 
 1475     /* brand with version and variant */
 1476     uuid_brand(uuid, 1);
 1477 
 1478     return UUID_RC_OK;
 1479 }
 1480 
 1481 
 1482 /* create UUID object */
 1483 static uuid_rc_t
 1484 uuid_create(uuid_t ** uuid)
 1485 {
 1486     uuid_t *obj;
 1487 
 1488     /* argument sanity check */
 1489     if (uuid == NULL)
 1490         return UUID_RC_ARG;
 1491 
 1492     /* allocate UUID object */
 1493     if ((obj = (uuid_t *) malloc(sizeof(uuid_t))) == NULL)
 1494         return UUID_RC_MEM;
 1495 
 1496     /* create PRNG, MD5 and SHA1 sub-objects */
 1497     if (brutus_prng_create(&obj->prng) != PRNG_RC_OK) {
 1498         free(obj);
 1499         return UUID_RC_INT;
 1500     }
 1501     if (brutus_md5_create(&obj->md5) != MD5_RC_OK) {
 1502         (void) brutus_prng_destroy(obj->prng);
 1503         free(obj);
 1504         return UUID_RC_INT;
 1505     }
 1506     if (brutus_sha1_create(&obj->sha1) != SHA1_RC_OK) {
 1507         (void) brutus_md5_destroy(obj->md5);
 1508         (void) brutus_prng_destroy(obj->prng);
 1509         free(obj);
 1510         return UUID_RC_INT;
 1511     }
 1512 
 1513     /* set UUID object initially to "Nil UUID" */
 1514     if (uuid_load(obj, "nil") != UUID_RC_OK) {
 1515         (void) brutus_sha1_destroy(obj->sha1);
 1516         (void) brutus_md5_destroy(obj->md5);
 1517         (void) brutus_prng_destroy(obj->prng);
 1518         free(obj);
 1519         return UUID_RC_INT;
 1520     }
 1521 
 1522     /* resolve MAC address for insertion into node field of UUIDs */
 1523     if (!brutus_mac_address((unsigned char *) (obj->mac), sizeof(obj->mac))) {
 1524         memset(obj->mac, 0, sizeof(obj->mac));
 1525         obj->mac[0] = BM_OCTET(1, 0, 0, 0, 0, 0, 0, 0);
 1526     }
 1527 
 1528     /* initialize time attributes */
 1529     obj->time_last.tv_sec = 0;
 1530     obj->time_last.tv_usec = 0;
 1531     obj->time_seq = 0;
 1532 
 1533     /* store result object */
 1534     *uuid = obj;
 1535 
 1536     return UUID_RC_OK;
 1537 }
 1538 
 1539 int
 1540 brutus_uuid(uuid_str_t uuid_str)
 1541 {
 1542     uuid_t *uuid;
 1543     uuid_rc_t rc;
 1544 
 1545     memset((void*)uuid_str, '\0', sizeof(uuid_str));
 1546 
 1547     if ((rc = uuid_create(&uuid)) != UUID_RC_OK)
 1548         return 1;
 1549     if ((rc = uuid_make(uuid)) != UUID_RC_OK)
 1550         return 1;
 1551     if ((rc = uuid_export_str(uuid, uuid_str)) != UUID_RC_OK)
 1552         return 1;
 1553     if ((rc = uuid_destroy(uuid)) != UUID_RC_OK)
 1554         return 1;
 1555 
 1556     return 0;
 1557 }