| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- *
- * Embedded Linux library
- *
- * Copyright (C) 2011-2014 Intel Corporation. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #define _GNU_SOURCE
- #include <stdio.h>
- #include "checksum.h"
- #include "random.h"
- #include "private.h"
- #include "useful.h"
- #include "uuid.h"
- const uint8_t L_UUID_NAMESPACE_DNS[16] = {
- 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
- };
- const uint8_t L_UUID_NAMESPACE_URL[16] = {
- 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
- };
- const uint8_t L_UUID_NAMESPACE_OID[16] = {
- 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
- };
- const uint8_t L_UUID_NAMESPACE_X500[16] = {
- 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
- 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8,
- };
- /* RFC 4122, Section 4.3 */
- static bool name_from_namespace(int version, const uint8_t nsid[16],
- const void *name,
- size_t name_size, uint8_t out_uuid[16])
- {
- enum l_checksum_type type;
- struct l_checksum *hash;
- struct iovec iov[2];
- if (unlikely(!out_uuid))
- return false;
- switch (version) {
- case 3:
- type = L_CHECKSUM_MD5;
- break;
- case 5:
- type = L_CHECKSUM_SHA1;
- break;
- default:
- return false;
- }
- hash = l_checksum_new(type);
- if (!hash)
- return false;
- iov[0].iov_base = (void *) nsid;
- iov[0].iov_len = 16;
- iov[1].iov_base = (void *) name;
- iov[1].iov_len = name_size;
- /* Compute the hash of the name space ID concatenated with the name. */
- l_checksum_updatev(hash, iov, 2);
- /* o Set octets zero through 3 of the time_low field to octets zero
- * through 3 of the hash.
- *
- * o Set octets zero and one of the time_mid field to octets 4 and 5 of
- * the hash.
- *
- * o Set octets zero and one of the time_hi_and_version field to octets
- * 6 and 7 of the hash.
- * o Set the four most significant bits (bits 12 through 15) of the
- * time_hi_and_version field to the appropriate 4-bit version number
- * from Section 4.1.3.
- *
- * o Set the clock_seq_hi_and_reserved field to octet 8 of the hash.
- * o Set the two most significant bits (bits 6 and 7) of the
- * clock_seq_hi_and_reserved to zero and one, respectively.
- *
- * o Set the clock_seq_low field to octet 9 of the hash.
- *
- * o Set octets zero through five of the node field to octets 10
- * through 15 of the hash.
- */
- l_checksum_get_digest(hash, out_uuid, 16);
- /* Set 4 MSB bits of time_hi_and_version field */
- out_uuid[6] &= 0x0f;
- out_uuid[6] |= version << 4;
- /* Set 2 MSB of clock_seq_hi_and_reserved to 10 */
- out_uuid[8] &= 0x3f;
- out_uuid[8] |= 0x80;
- l_checksum_free(hash);
- return true;
- }
- LIB_EXPORT bool l_uuid_v3(const uint8_t nsid[16], const void *name,
- size_t name_size, uint8_t out_uuid[16])
- {
- return name_from_namespace(3, nsid, name, name_size, out_uuid);
- }
- LIB_EXPORT bool l_uuid_v5(const uint8_t nsid[16], const void *name,
- size_t name_size, uint8_t out_uuid[16])
- {
- return name_from_namespace(5, nsid, name, name_size, out_uuid);
- }
- /* RFC 4122, Section 4.4 */
- LIB_EXPORT bool l_uuid_v4(uint8_t out_uuid[16])
- {
- if (unlikely(!out_uuid))
- return false;
- if (!l_getrandom(out_uuid, 16))
- return false;
- /*
- * o Set the two most significant bits (bits 6 and 7) of the
- * clock_seq_hi_and_reserved to zero and one, respectively.
- *
- * o Set the four most significant bits (bits 12 through 15) of the
- * time_hi_and_version field to the 4-bit version number from
- * Section 4.1.3.
- *
- * o Set all the other bits to randomly (or pseudo-randomly) chosen
- * values.
- */
- /* Set 4 MSB bits of time_hi_and_version field */
- out_uuid[6] &= 0x0f;
- out_uuid[6] |= 4 << 4;
- /* Set 2 MSB of clock_seq_hi_and_reserved to 10 */
- out_uuid[8] &= 0x3f;
- out_uuid[8] |= 0x80;
- return true;
- }
- /**
- * l_uuid_is_valid:
- * @uuid: UUID to check.
- *
- * Checks whether the given UUID is valid according to RFC 4122. This function
- * checks that the version field is set properly and the variant of the UUID
- * is set to RFC 4122.
- *
- * Returns: Whether the UUID is valid
- **/
- LIB_EXPORT bool l_uuid_is_valid(const uint8_t uuid[16])
- {
- unsigned int version;
- unsigned int variant;
- if (!uuid)
- return false;
- variant = uuid[8] >> 6;
- if (variant != 2)
- return false;
- version = uuid[6] >> 4;
- if (version < 1 || version > 5)
- return false;
- return true;
- }
- LIB_EXPORT enum l_uuid_version l_uuid_get_version(const uint8_t uuid[16])
- {
- unsigned int version;
- version = uuid[6] >> 4;
- return version;
- }
- LIB_EXPORT bool l_uuid_to_string(const uint8_t uuid[16],
- char *dest, size_t dest_size)
- {
- int n;
- n = snprintf(dest, dest_size, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x-%02x%02x%02x%02x%02x%02x",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5],
- uuid[6], uuid[7],
- uuid[8], uuid[9],
- uuid[10], uuid[11], uuid[12],
- uuid[13], uuid[14], uuid[15]);
- if (n < 0 || (size_t) n >= dest_size)
- return false;
- return true;
- }
- LIB_EXPORT bool l_uuid_from_string(const char *src, uint8_t uuid[16])
- {
- uint8_t buf[16];
- int n;
- /*
- * textual representation: 32 hex digits + 4 group separators
- */
- if (strlen(src) < 16 * 2 + 4)
- return false;
- n = sscanf(src,
- "%02hhx%02hhx%02hhx%02hhx-"
- "%02hhx%02hhx-"
- "%02hhx%02hhx-"
- "%02hhx%02hhx-"
- "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
- &buf[0], &buf[1], &buf[2], &buf[3],
- &buf[4], &buf[5],
- &buf[6], &buf[7],
- &buf[8], &buf[9],
- &buf[10], &buf[11], &buf[12],
- &buf[13], &buf[14], &buf[15]);
- if (n != 16)
- return false;
- if (!l_uuid_is_valid(buf))
- return false;
- memcpy(uuid, buf, sizeof(buf));
- return true;
- }
|