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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
_ ___ ____ ____ ____ _ _
|_|_ _ / _ \/ ___/ ___|| _ \ _ _ _ _(_) __| |
_|_||_| | | | \___ \___ \| |_) | | | | | | | | |/ _` |
|_||_|_| | |_| |___) |__) | __/ | |_| | |_| | | (_| |
|_|_|_| \___/|____/____/|_| \__,_|\__,_|_|\__,_|
OSSP uuid - Universally Unique Identifier
HISTORY
During OSSP uuid we were totally puzzled by a subtle bug in the UUID
standards related to the generation of multi-cast MAC addresses.
This part of the history shows a very interesting technical bug,
the unusual way of having to fix a standard (which was multiple
times revised by different standard authorities, including the
IETF, the OpenGroup and ISO/IEC) afterwards plus the fixing of six
implementations into which the bug was inherited similarly. Below are
some snapshot of this part of history: the first implementation fix
(for FreeBSD) and the notification of the IETF standards authors.
___________________________________________________________________________
Date: Fri, 13 Feb 2004 16:09:31 +0100
From: "Ralf S. Engelschall" <rse@en1.engelschall.com>
To: paulle@microsoft.com, michael@neonym.net, rsalz@datapower.com
Subject: [PATCH] draft-mealling-uuid-urn-02.txt
Message-ID: <20040213150931.GA7656@engelschall.com>
During implementation of OSSP uuid (a flexible CLI and C API for
generation and partial decoding of version 1, 3 and 4 UUIDs, see
http://www.ossp.org/pkg/lib/uuid/ for details), I discovered a nasty bug
in the generation of random multicast MAC addresses. It is present in
all standards and drafts (both expired ones and current ones) and was
also inherited (until I fixed it by submitting patches to the authors
recently) by all six freely available UUID implementations (Apache APR,
FreeBSD uuidgen(2), Java JUG, Linux's libuuid from e2fsutil, Perl's
Data::UUID and WINE's UUID generator)).
In case no real/physical IEEE 802 address is available, both the
expired "draft-leach-uuids-guids-01" (section "4. Node IDs when no IEEE
802 network card is available"), RFC 2518 (section "6.4.1 Node Field
Generation Without the IEEE 802 Address") and now even your current
"draft-mealling-uuid-urn-02.txt" (section "4.5 Node IDs that do not
identify the host") recommend:
"A better solution is to obtain a 47-bit cryptographic quality
random number, and use it as the low 47 bits of the node ID, with
the _most_ significant bit of the first octet of the node ID set to
one. This bit is the unicast/multicast bit, which will never be set
in IEEE 802 addresses obtained from network cards; hence, there can
never be a conflict between UUIDs generated by machines with and
without network cards."
Unfortunately, this incorrectly explains how to implement this and even
the example implementation (draft-mealling-uuid-urn-02.txt, "Appendix
A. Appendix A - Sample Implementation") inherited this. Correct is
"the _least_ significant bit of the first octet of the node ID" as the
multicast bit in a memory and hexadecimal string representation of a
48-bit IEEE 802 MAC address.
This standards bug arised from a false interpretation, as the multicast
bit is actually the _most_ significant bit in IEEE 802.3 (Ethernet)
_transmission order_ of an IEEE 802 MAC address. But you forgot that the
bitwise order of an _octet_ from a MAC address _memory_ and hexadecimal
string representation is still always from left (MSB, bit 7) to right
(LSB, bit 0). And the standard deals with memory representations only,
so the transmission order of a MAC doesnt' matter here.
As mentioned, OSSP uuid already implements this correctly. The FreeBSD
uuidgen(2) and Apache APR generators I've also fixed myself recently in
CVS. And for the remaining implementations I've submitted patches to the
authors and they all (except for WINE) responded that they took over the
patch. So the results of this long-standing bug we were able to fix --
at least for the free software world ;-). What is now remaining is that
you finally also should fix this in your standard so the bug does not
spread any longer into other implementations.
Here is the minimal required patch against your draft:
--- draft-mealling-uuid-urn-02.txt.orig Mon Feb 2 21:50:35 2004
+++ draft-mealling-uuid-urn-02.txt Fri Feb 13 15:41:49 2004
@@ -751,7 +751,7 @@
[6], and the cost was US$550.
A better solution is to obtain a 47-bit cryptographic quality random
- number, and use it as the low 47 bits of the node ID, with the most
+ number, and use it as the low 47 bits of the node ID, with the least
significant bit of the first octet of the node ID set to one. This
bit is the unicast/multicast bit, which will never be set in IEEE 802
addresses obtained from network cards; hence, there can never be a
@@ -1369,7 +1369,7 @@
}
else {
get_random_info(seed);
- seed[0] |= 0x80;
+ seed[0] |= 0x01;
memcpy(&saved_node, seed, sizeof saved_node);
fp = fopen("nodeid", "wb");
if (fp) {
But I recommend you to perhaps also add one or two sentences which
explain what I explained above (the difference between memory and
transmission order), just to make sure people are not confused in the
other direction and then think there is a bug (in the then fixed and
correct) standard, because they know about the transmission order of MAC
addresses.
Yours,
Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com
Date: Fri, 13 Feb 2004 11:05:51 -0500
From: Rich Salz <rsalz@datapower.com>
To: rse@engelschall.com
Cc: paulle@microsoft.com, michael@neonym.net
Message-ID: <402CF5DF.4020601@datapower.com>
Subject: Re: [PATCH] draft-mealling-uuid-urn-02.txt
References: <20040213150931.GA7656@engelschall.com>
Content-Length: 431
Lines: 11
Thanks for writing, Ralf.
You're correct, and this has been noted by the IESG and will be fixed in
the next draft. It's unfortunate we made it this far with the bug.
/r$
--
Rich Salz, Chief Security Architect
DataPower Technology http://www.datapower.com
XS40 XML Security Gateway http://www.datapower.com/products/xs40.html
XML Security Overview http://www.datapower.com/xmldev/xmlsecurity.html
Date: Thu, 22 Jan 2004 05:34:11 -0800 (PST)
From: "Ralf S. Engelschall" <rse@FreeBSD.org>
Message-Id: <200401221334.i0MDYB1K018137@repoman.freebsd.org>
To: src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org
Subject: cvs commit: src/sys/kern kern_uuid.c
X-FreeBSD-CVS-Branch: HEAD
X-Loop: FreeBSD.ORG
Content-Length: 1907
Lines: 42
rse 2004/01/22 05:34:11 PST
FreeBSD src repository
Modified files:
sys/kern kern_uuid.c
Log:
Fix generation of random multicast MAC address.
In case no real/physical IEEE 802 address is available, both the expired
"draft-leach-uuids-guids-01" (section "4. Node IDs when no IEEE 802
network card is available") and RFC 2518 (section "6.4.1 Node Field
Generation Without the IEEE 802 Address") recommend (quoted from RFC
2518):
"The ideal solution is to obtain a 47 bit cryptographic quality random
number, and use it as the low 47 bits of the node ID, with the _most_
significant bit of the first octet of the node ID set to 1. This bit
is the unicast/multicast bit, which will never be set in IEEE 802
addresses obtained from network cards; hence, there can never be a
conflict between UUIDs generated by machines with and without network
cards."
Unfortunately, this incorrectly explains how to implement this and
the FreeBSD UUID generator code inherited this generation bug from
the broken reference code in the standards draft. They should instead
specify the "_least_ significant bit of the first octet of the node ID"
as the multicast bit in a memory and hexadecimal string representation
of a 48-bit IEEE 802 MAC address.
This standards bug arised from a false interpretation, as the multicast
bit is actually the _most_ significant bit in IEEE 802.3 (Ethernet)
_transmission order_ of an IEEE 802 MAC address. The standards authors
forgot that the bitwise order of an _octet_ from a MAC address _memory_
and hexadecimal string representation is still always from left (MSB,
bit 7) to right (LSB, bit 0).
Fortunately, this UUID generation bug could have occurred on systems
without any Ethernet NICs only.
Revision Changes Path
1.7 +1 -1 src/sys/kern/kern_uuid.c
Date: Thu, 22 Jan 2004 15:20:22 -0800
From: Marcel Moolenaar <marcel@xcllnt.net>
To: "Ralf S. Engelschall" <rse@FreeBSD.org>
Cc: src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org
Subject: Re: cvs commit: src/sys/kern kern_uuid.c
Message-ID: <20040122232022.GA77798@ns1.xcllnt.net>
References: <200401221334.i0MDYB1K018137@repoman.freebsd.org>
Content-Length: 380
Lines: 14
On Thu, Jan 22, 2004 at 05:34:11AM -0800, Ralf S. Engelschall wrote:
> rse 2004/01/22 05:34:11 PST
>
> FreeBSD src repository
>
> Modified files:
> sys/kern kern_uuid.c
> Log:
> Fix generation of random multicast MAC address.
An excellent catch and an outstanding commit log. Chapeau!
--
Marcel Moolenaar USPA: A-39004 marcel@xcllnt.net
___________________________________________________________________________
Index: ChangeLog
===================================================================
RCS file: /e/ossp/cvs/ossp-pkg/uuid/ChangeLog,v
retrieving revision 1.42
diff -u -d -r1.42 ChangeLog
--- ChangeLog 13 Feb 2004 16:17:07 -0000 1.42
+++ ChangeLog 13 Feb 2004 21:01:07 -0000
@@ -13,6 +13,14 @@
Changes between 0.9.6 and 0.9.7 (11-Feb-2004 to 13-Feb-2004)
+ o remove --with-rfc2518 option and functionality because
+ even the IETF/IESG has finally approved our report about the broken
+ random multicast MAC address generation in the standard (and
+ will fix it in new versions of the draft-mealling-uuid-urn). So,
+ finally get rid of this broken-by-design backward compatibility
+ functionality.
+ [Ralf S. Engelschall]
+
o Add support to uuid(1) CLI for decoding from stdin for
both binary and string representations.
[Ralf S. Engelschall]
Index: uuid.ac
===================================================================
RCS file: /e/ossp/cvs/ossp-pkg/uuid/uuid.ac,v
retrieving revision 1.10
diff -u -d -r1.10 uuid.ac
--- uuid.ac 11 Feb 2004 14:38:40 -0000 1.10
+++ uuid.ac 13 Feb 2004 19:20:32 -0000
@@ -71,12 +71,6 @@
AC_CHECK_SIZEOF(unsigned long long, 8)
dnl # options
- AC_ARG_WITH(rfc2518,
- AC_HELP_STRING([--with-rfc2518], [use incorrect generation of IEEE 802 multicast addresses according to RFC2518]),
- [ac_cv_with_rfc2518=$withval], [ac_cv_with_rfc2518=no])
- if test ".$ac_cv_with_rfc2518" = ".yes"; then
- AC_DEFINE(WITH_RFC2518, 1, [whether to use incorrect generation of IEEE 802 multicast addresses according to RFC2518])
- fi
AC_ARG_WITH(dce,
AC_HELP_STRING([--with-dce], [build DCE 1.1 backward compatibility API]),
[ac_cv_with_dce=$withval], [ac_cv_with_dce=no])
Index: uuid.c
===================================================================
RCS file: /e/ossp/cvs/ossp-pkg/uuid/uuid.c,v
retrieving revision 1.44
diff -u -d -r1.44 uuid.c
--- uuid.c 19 Jan 2004 14:56:35 -0000 1.44
+++ uuid.c 13 Feb 2004 19:22:01 -0000
@@ -61,69 +61,9 @@
Unix UTC base time is January 1, 1970) */
#define UUID_TIMEOFFSET "01B21DD213814000"
-/* IEEE 802 MAC address encoding/decoding bit fields
-
- ATTENTION:
-
- In case no real/physical IEEE 802 address is available, both
- "draft-leach-uuids-guids-01" (section "4. Node IDs when no IEEE 802
- network card is available") and RFC 2518 (section "6.4.1 Node Field
- Generation Without the IEEE 802 Address") recommend (quoted from RFC
- 2518):
-
- "The ideal solution is to obtain a 47 bit cryptographic quality
- random number, and use it as the low 47 bits of the node ID, with
- the most significant bit of the first octet of the node ID set to
- 1. This bit is the unicast/multicast bit, which will never be set
- in IEEE 802 addresses obtained from network cards; hence, there can
- never be a conflict between UUIDs generated by machines with and
- without network cards."
-
- This passage clearly explains the intention to use IEEE 802 multicast
- addresses. Unfortunately, it incorrectly explains how to implement
- this! It should instead specify the "*LEAST* significant bit of the
- first octet of the node ID" as the multicast bit in a memory and
- hexadecimal string representation of a 48-bit IEEE 802 MAC address.
-
- Unfortunately, even the reference implementation included in the
- expired IETF "draft-leach-uuids-guids-01" incorrectly set the
- multicast bit with an OR bit operation and an incorrect mask of
- 0x80. Hence, several other UUID implementations found on the
- Internet have inherited this bug.
-
- Luckily, neither DCE 1.1 nor ISO/IEC 11578:1996 are affected by this
- problem. They disregard the topic of missing IEEE 802 addresses
- entirely, and thus avoid adopting this bug from the original draft
- and code ;-)
-
- It seems that this standards bug arises from a false interpretation,
- as the multicast bit is actually the *MOST* significant bit in IEEE
- 802.3 (Ethernet) _transmission order_ of an IEEE 802 MAC address. The
- authors were likely not aware that the bitwise order of an octet from
- a MAC address memory and hexadecimal string representation is still
- always from left (MSB, bit 7) to right (LSB, bit 0).
-
- For more information, see "Understanding Physical Addresses" in
- "Ethernet -- The Definitive Guide", p.43, and the section "ETHERNET
- MULTICAST ADDRESSES" in http://www.iana.org/assignments/ethernet-numbers.
-
- At OSSP, we do it the intended/correct way and generate a real
- IEEE 802 multicast address. Those wanting to encode broken IEEE
- 802 MAC addresses (as specified) can nevertheless use a brain dead
- compile-time option to switch off the correct behavior. When decoding
- we always use the correct behavior of course. */
-
-/* encoding */
-#ifdef WITH_RFC2518
-#define IEEE_MAC_MCBIT_ENC BM_OCTET(1,0,0,0,0,0,0,0)
-#else
-#define IEEE_MAC_MCBIT_ENC BM_OCTET(0,0,0,0,0,0,0,1)
-#endif
-#define IEEE_MAC_LOBIT_ENC BM_OCTET(0,0,0,0,0,0,1,0)
-
-/* decoding */
-#define IEEE_MAC_MCBIT_DEC BM_OCTET(0,0,0,0,0,0,0,1)
-#define IEEE_MAC_LOBIT_DEC BM_OCTET(0,0,0,0,0,0,1,0)
+/* IEEE 802 MAC address encoding/decoding bit fields */
+#define IEEE_MAC_MCBIT BM_OCTET(0,0,0,0,0,0,0,1)
+#define IEEE_MAC_LOBIT BM_OCTET(0,0,0,0,0,0,1,0)
/* IEEE 802 MAC address octet length */
#define IEEE_MAC_OCTETS 6
@@ -622,8 +562,8 @@
(unsigned int)uuid->obj.node[3],
(unsigned int)uuid->obj.node[4],
(unsigned int)uuid->obj.node[5],
- (uuid->obj.node[0] & IEEE_MAC_LOBIT_DEC ? "local" : "global"),
- (uuid->obj.node[0] & IEEE_MAC_MCBIT_DEC ? "multicast" : "unicast"));
+ (uuid->obj.node[0] & IEEE_MAC_LOBIT ? "local" : "global"),
+ (uuid->obj.node[0] & IEEE_MAC_MCBIT ? "multicast" : "unicast"));
}
else {
/* decode anything else as hexadecimal byte-string only */
@@ -843,8 +783,8 @@
if ((mode & UUID_MAKE_MC) || (uuid->mac[0] & BM_OCTET(1,0,0,0,0,0,0,0))) {
/* generate random IEEE 802 local multicast MAC address */
prng_data(uuid->prng, (void *)&(uuid->obj.node), sizeof(uuid->obj.node));
- uuid->obj.node[0] |= IEEE_MAC_MCBIT_ENC;
- uuid->obj.node[0] |= IEEE_MAC_LOBIT_ENC;
+ uuid->obj.node[0] |= IEEE_MAC_MCBIT;
+ uuid->obj.node[0] |= IEEE_MAC_LOBIT;
}
else {
/* use real regular MAC address */
|