359 lines
16 KiB
Plaintext
359 lines
16 KiB
Plaintext
_ ___ ____ ____ ____ _ _
|
|
|_|_ _ / _ \/ ___/ ___|| _ \ _ _ _ _(_) __| |
|
|
_|_||_| | | | \___ \___ \| |_) | | | | | | | | |/ _` |
|
|
|_||_|_| | |_| |___) |__) | __/ | |_| | |_| | | (_| |
|
|
|_|_|_| \___/|____/____/|_| \__,_|\__,_|_|\__,_|
|
|
|
|
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 */
|