1*1802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fab1c232SHuang Ying /* 3fab1c232SHuang Ying * Unified UUID/GUID definition 4fab1c232SHuang Ying * 5e3a93bceSAndy Shevchenko * Copyright (C) 2009, 2016 Intel Corp. 6fab1c232SHuang Ying * Huang Ying <ying.huang@intel.com> 7fab1c232SHuang Ying */ 8fab1c232SHuang Ying 9fab1c232SHuang Ying #include <linux/kernel.h> 102b1b0d66SAndy Shevchenko #include <linux/ctype.h> 112b1b0d66SAndy Shevchenko #include <linux/errno.h> 128bc3bcc9SPaul Gortmaker #include <linux/export.h> 13fab1c232SHuang Ying #include <linux/uuid.h> 14fab1c232SHuang Ying #include <linux/random.h> 15fab1c232SHuang Ying 16ef40dda5SChristoph Hellwig const guid_t guid_null; 17ef40dda5SChristoph Hellwig EXPORT_SYMBOL(guid_null); 18ef40dda5SChristoph Hellwig const uuid_t uuid_null; 19ef40dda5SChristoph Hellwig EXPORT_SYMBOL(uuid_null); 20ef40dda5SChristoph Hellwig 21f9727a17SChristoph Hellwig const u8 guid_index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; 22f9727a17SChristoph Hellwig const u8 uuid_index[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 232b1b0d66SAndy Shevchenko 24d063623bSRandy Dunlap /** 25d063623bSRandy Dunlap * generate_random_uuid - generate a random UUID 26d063623bSRandy Dunlap * @uuid: where to put the generated UUID 27d063623bSRandy Dunlap * 288da4b8c4SAndy Shevchenko * Random UUID interface 298da4b8c4SAndy Shevchenko * 30d063623bSRandy Dunlap * Used to create a Boot ID or a filesystem UUID/GUID, but can be 31d063623bSRandy Dunlap * useful for other kernel drivers. 328da4b8c4SAndy Shevchenko */ 338da4b8c4SAndy Shevchenko void generate_random_uuid(unsigned char uuid[16]) 348da4b8c4SAndy Shevchenko { 358da4b8c4SAndy Shevchenko get_random_bytes(uuid, 16); 368da4b8c4SAndy Shevchenko /* Set UUID version to 4 --- truly random generation */ 378da4b8c4SAndy Shevchenko uuid[6] = (uuid[6] & 0x0F) | 0x40; 388da4b8c4SAndy Shevchenko /* Set the UUID variant to DCE */ 398da4b8c4SAndy Shevchenko uuid[8] = (uuid[8] & 0x3F) | 0x80; 408da4b8c4SAndy Shevchenko } 418da4b8c4SAndy Shevchenko EXPORT_SYMBOL(generate_random_uuid); 428da4b8c4SAndy Shevchenko 43fab1c232SHuang Ying static void __uuid_gen_common(__u8 b[16]) 44fab1c232SHuang Ying { 45cedddb00SAkinobu Mita prandom_bytes(b, 16); 46fab1c232SHuang Ying /* reversion 0b10 */ 47fab1c232SHuang Ying b[8] = (b[8] & 0x3F) | 0x80; 48fab1c232SHuang Ying } 49fab1c232SHuang Ying 50f9727a17SChristoph Hellwig void guid_gen(guid_t *lu) 51fab1c232SHuang Ying { 52fab1c232SHuang Ying __uuid_gen_common(lu->b); 53fab1c232SHuang Ying /* version 4 : random generation */ 54fab1c232SHuang Ying lu->b[7] = (lu->b[7] & 0x0F) | 0x40; 55fab1c232SHuang Ying } 56f9727a17SChristoph Hellwig EXPORT_SYMBOL_GPL(guid_gen); 57fab1c232SHuang Ying 58f9727a17SChristoph Hellwig void uuid_gen(uuid_t *bu) 59fab1c232SHuang Ying { 60fab1c232SHuang Ying __uuid_gen_common(bu->b); 61fab1c232SHuang Ying /* version 4 : random generation */ 62fab1c232SHuang Ying bu->b[6] = (bu->b[6] & 0x0F) | 0x40; 63fab1c232SHuang Ying } 64f9727a17SChristoph Hellwig EXPORT_SYMBOL_GPL(uuid_gen); 652b1b0d66SAndy Shevchenko 662b1b0d66SAndy Shevchenko /** 67d063623bSRandy Dunlap * uuid_is_valid - checks if a UUID string is valid 682b1b0d66SAndy Shevchenko * @uuid: UUID string to check 692b1b0d66SAndy Shevchenko * 702b1b0d66SAndy Shevchenko * Description: 712b1b0d66SAndy Shevchenko * It checks if the UUID string is following the format: 722b1b0d66SAndy Shevchenko * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 73d063623bSRandy Dunlap * 742b1b0d66SAndy Shevchenko * where x is a hex digit. 752b1b0d66SAndy Shevchenko * 762b1b0d66SAndy Shevchenko * Return: true if input is valid UUID string. 772b1b0d66SAndy Shevchenko */ 782b1b0d66SAndy Shevchenko bool uuid_is_valid(const char *uuid) 792b1b0d66SAndy Shevchenko { 802b1b0d66SAndy Shevchenko unsigned int i; 812b1b0d66SAndy Shevchenko 822b1b0d66SAndy Shevchenko for (i = 0; i < UUID_STRING_LEN; i++) { 832b1b0d66SAndy Shevchenko if (i == 8 || i == 13 || i == 18 || i == 23) { 842b1b0d66SAndy Shevchenko if (uuid[i] != '-') 852b1b0d66SAndy Shevchenko return false; 862b1b0d66SAndy Shevchenko } else if (!isxdigit(uuid[i])) { 872b1b0d66SAndy Shevchenko return false; 882b1b0d66SAndy Shevchenko } 892b1b0d66SAndy Shevchenko } 902b1b0d66SAndy Shevchenko 912b1b0d66SAndy Shevchenko return true; 922b1b0d66SAndy Shevchenko } 932b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_is_valid); 942b1b0d66SAndy Shevchenko 95f9727a17SChristoph Hellwig static int __uuid_parse(const char *uuid, __u8 b[16], const u8 ei[16]) 962b1b0d66SAndy Shevchenko { 972b1b0d66SAndy Shevchenko static const u8 si[16] = {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34}; 982b1b0d66SAndy Shevchenko unsigned int i; 992b1b0d66SAndy Shevchenko 1002b1b0d66SAndy Shevchenko if (!uuid_is_valid(uuid)) 1012b1b0d66SAndy Shevchenko return -EINVAL; 1022b1b0d66SAndy Shevchenko 1032b1b0d66SAndy Shevchenko for (i = 0; i < 16; i++) { 104bc9dc9d5SBjørn Mork int hi = hex_to_bin(uuid[si[i] + 0]); 105bc9dc9d5SBjørn Mork int lo = hex_to_bin(uuid[si[i] + 1]); 1062b1b0d66SAndy Shevchenko 1072b1b0d66SAndy Shevchenko b[ei[i]] = (hi << 4) | lo; 1082b1b0d66SAndy Shevchenko } 1092b1b0d66SAndy Shevchenko 1102b1b0d66SAndy Shevchenko return 0; 1112b1b0d66SAndy Shevchenko } 1122b1b0d66SAndy Shevchenko 113f9727a17SChristoph Hellwig int guid_parse(const char *uuid, guid_t *u) 1142b1b0d66SAndy Shevchenko { 115f9727a17SChristoph Hellwig return __uuid_parse(uuid, u->b, guid_index); 1162b1b0d66SAndy Shevchenko } 117f9727a17SChristoph Hellwig EXPORT_SYMBOL(guid_parse); 1182b1b0d66SAndy Shevchenko 119f9727a17SChristoph Hellwig int uuid_parse(const char *uuid, uuid_t *u) 1202b1b0d66SAndy Shevchenko { 121f9727a17SChristoph Hellwig return __uuid_parse(uuid, u->b, uuid_index); 1222b1b0d66SAndy Shevchenko } 123f9727a17SChristoph Hellwig EXPORT_SYMBOL(uuid_parse); 124