blob: 10035018671f7e044cfdbdaf3cf4b35de1f04332 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
// file : libbutl/uuid-macos.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#ifndef BUILD2_BOOTSTRAP
#include <libbutl/uuid.hxx>
#include <CoreFoundation/CFUUID.h>
#include <cassert>
#include <cstring> // memcpy()
using namespace std;
namespace butl
{
void
uuid_throw_weak (); // uuid.cxx
uuid uuid_system_generator::
generate (bool strong)
{
// The common way to generate a UUID on Mac OS is with the CFUUIDCreate()
// function from the CoreFoundation framework. Interestingly, if we look
// at the implementation (yes, the CF source code is available), we will
// see that it uses the <uuid/uuid.h> API which looks like a customized
// implementation from e2fsprogs that itself is a precursor to libuuid
// from util-linux.
//
// More specifically (and at least as of CF version 1153.18), it calls
// uuid_generate_random() unless the CFUUIDVersionNumber environment
// variable is set to 1, in which case it calls uuid_generate_time(). It
// also appears to serialize these calls so the implementation should be
// thread-safe (see the Linux implementation for background; this is also
// the reason why we don't want to use the low-level API directly even if
// we provide our own synchronization: if other code in the process calls
// CFUUIDCreate() then we will end up with a race).
//
// In theory the use of uuid_generate_random() is bad news since it will
// produce weak pseudo-random UUIDs if no high-quality randomness is
// available (unlike uuid_generate() which will only produce strong random
// UUIDs falling back to the MAC/time-based ones; see uuid_generate(3) for
// details).
//
// In practice (and at least as of Mac OS libc version 1244.30), however,
// uuid_generate_random() uses arc4random(3) which reportedly produces
// high-quality randomness (and uuid_generate() simply always calls it).
//
CFUUIDRef h (CFUUIDCreate (NULL));
CFUUIDBytes d (CFUUIDGetUUIDBytes (h));
CFRelease (h);
uint8_t a[16];
memcpy (a, &d, 16); // CFUUIDBytes is POD.
uuid r (a);
assert (r.variant () == uuid_variant::dce); // Sanity check.
// If this is a MAC/time-based UUID, then it's possible the time was not
// obtained in a collision-safe manner (looking at the implementation this
// seems to be the case; see the Linux implementation for background).
//
if (strong && r.version () != uuid_version::random)
uuid_throw_weak ();
return r;
}
void uuid_system_generator::
initialize ()
{
}
void uuid_system_generator::
terminate ()
{
}
}
#endif // BUILD2_BOOTSTRAP
|