xref: /openbmc/linux/lib/uuid.c (revision e3a93bce69ad3e2c38927abe311b8cb4f17abbaf)
1fab1c232SHuang Ying /*
2fab1c232SHuang Ying  * Unified UUID/GUID definition
3fab1c232SHuang Ying  *
4*e3a93bceSAndy Shevchenko  * Copyright (C) 2009, 2016 Intel Corp.
5fab1c232SHuang Ying  *	Huang Ying <ying.huang@intel.com>
6fab1c232SHuang Ying  *
7fab1c232SHuang Ying  * This program is free software; you can redistribute it and/or
8fab1c232SHuang Ying  * modify it under the terms of the GNU General Public License version
9fab1c232SHuang Ying  * 2 as published by the Free Software Foundation;
10fab1c232SHuang Ying  *
11fab1c232SHuang Ying  * This program is distributed in the hope that it will be useful,
12fab1c232SHuang Ying  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fab1c232SHuang Ying  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14fab1c232SHuang Ying  * GNU General Public License for more details.
15fab1c232SHuang Ying  */
16fab1c232SHuang Ying 
17fab1c232SHuang Ying #include <linux/kernel.h>
182b1b0d66SAndy Shevchenko #include <linux/ctype.h>
192b1b0d66SAndy Shevchenko #include <linux/errno.h>
208bc3bcc9SPaul Gortmaker #include <linux/export.h>
21fab1c232SHuang Ying #include <linux/uuid.h>
22fab1c232SHuang Ying #include <linux/random.h>
23fab1c232SHuang Ying 
242b1b0d66SAndy Shevchenko const u8 uuid_le_index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
252b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_le_index);
262b1b0d66SAndy Shevchenko const u8 uuid_be_index[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
272b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_be_index);
282b1b0d66SAndy Shevchenko 
298da4b8c4SAndy Shevchenko /***************************************************************
308da4b8c4SAndy Shevchenko  * Random UUID interface
318da4b8c4SAndy Shevchenko  *
328da4b8c4SAndy Shevchenko  * Used here for a Boot ID, but can be useful for other kernel
338da4b8c4SAndy Shevchenko  * drivers.
348da4b8c4SAndy Shevchenko  ***************************************************************/
358da4b8c4SAndy Shevchenko 
368da4b8c4SAndy Shevchenko /*
378da4b8c4SAndy Shevchenko  * Generate random UUID
388da4b8c4SAndy Shevchenko  */
398da4b8c4SAndy Shevchenko void generate_random_uuid(unsigned char uuid[16])
408da4b8c4SAndy Shevchenko {
418da4b8c4SAndy Shevchenko 	get_random_bytes(uuid, 16);
428da4b8c4SAndy Shevchenko 	/* Set UUID version to 4 --- truly random generation */
438da4b8c4SAndy Shevchenko 	uuid[6] = (uuid[6] & 0x0F) | 0x40;
448da4b8c4SAndy Shevchenko 	/* Set the UUID variant to DCE */
458da4b8c4SAndy Shevchenko 	uuid[8] = (uuid[8] & 0x3F) | 0x80;
468da4b8c4SAndy Shevchenko }
478da4b8c4SAndy Shevchenko EXPORT_SYMBOL(generate_random_uuid);
488da4b8c4SAndy Shevchenko 
49fab1c232SHuang Ying static void __uuid_gen_common(__u8 b[16])
50fab1c232SHuang Ying {
51cedddb00SAkinobu Mita 	prandom_bytes(b, 16);
52fab1c232SHuang Ying 	/* reversion 0b10 */
53fab1c232SHuang Ying 	b[8] = (b[8] & 0x3F) | 0x80;
54fab1c232SHuang Ying }
55fab1c232SHuang Ying 
56fab1c232SHuang Ying void uuid_le_gen(uuid_le *lu)
57fab1c232SHuang Ying {
58fab1c232SHuang Ying 	__uuid_gen_common(lu->b);
59fab1c232SHuang Ying 	/* version 4 : random generation */
60fab1c232SHuang Ying 	lu->b[7] = (lu->b[7] & 0x0F) | 0x40;
61fab1c232SHuang Ying }
62fab1c232SHuang Ying EXPORT_SYMBOL_GPL(uuid_le_gen);
63fab1c232SHuang Ying 
64fab1c232SHuang Ying void uuid_be_gen(uuid_be *bu)
65fab1c232SHuang Ying {
66fab1c232SHuang Ying 	__uuid_gen_common(bu->b);
67fab1c232SHuang Ying 	/* version 4 : random generation */
68fab1c232SHuang Ying 	bu->b[6] = (bu->b[6] & 0x0F) | 0x40;
69fab1c232SHuang Ying }
70fab1c232SHuang Ying EXPORT_SYMBOL_GPL(uuid_be_gen);
712b1b0d66SAndy Shevchenko 
722b1b0d66SAndy Shevchenko /**
732b1b0d66SAndy Shevchenko   * uuid_is_valid - checks if UUID string valid
742b1b0d66SAndy Shevchenko   * @uuid:	UUID string to check
752b1b0d66SAndy Shevchenko   *
762b1b0d66SAndy Shevchenko   * Description:
772b1b0d66SAndy Shevchenko   * It checks if the UUID string is following the format:
782b1b0d66SAndy Shevchenko   *	xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
792b1b0d66SAndy Shevchenko   * where x is a hex digit.
802b1b0d66SAndy Shevchenko   *
812b1b0d66SAndy Shevchenko   * Return: true if input is valid UUID string.
822b1b0d66SAndy Shevchenko   */
832b1b0d66SAndy Shevchenko bool uuid_is_valid(const char *uuid)
842b1b0d66SAndy Shevchenko {
852b1b0d66SAndy Shevchenko 	unsigned int i;
862b1b0d66SAndy Shevchenko 
872b1b0d66SAndy Shevchenko 	for (i = 0; i < UUID_STRING_LEN; i++) {
882b1b0d66SAndy Shevchenko 		if (i == 8 || i == 13 || i == 18 || i == 23) {
892b1b0d66SAndy Shevchenko 			if (uuid[i] != '-')
902b1b0d66SAndy Shevchenko 				return false;
912b1b0d66SAndy Shevchenko 		} else if (!isxdigit(uuid[i])) {
922b1b0d66SAndy Shevchenko 			return false;
932b1b0d66SAndy Shevchenko 		}
942b1b0d66SAndy Shevchenko 	}
952b1b0d66SAndy Shevchenko 
962b1b0d66SAndy Shevchenko 	return true;
972b1b0d66SAndy Shevchenko }
982b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_is_valid);
992b1b0d66SAndy Shevchenko 
1002b1b0d66SAndy Shevchenko static int __uuid_to_bin(const char *uuid, __u8 b[16], const u8 ei[16])
1012b1b0d66SAndy Shevchenko {
1022b1b0d66SAndy Shevchenko 	static const u8 si[16] = {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34};
1032b1b0d66SAndy Shevchenko 	unsigned int i;
1042b1b0d66SAndy Shevchenko 
1052b1b0d66SAndy Shevchenko 	if (!uuid_is_valid(uuid))
1062b1b0d66SAndy Shevchenko 		return -EINVAL;
1072b1b0d66SAndy Shevchenko 
1082b1b0d66SAndy Shevchenko 	for (i = 0; i < 16; i++) {
1092b1b0d66SAndy Shevchenko 		int hi = hex_to_bin(uuid[si[i]] + 0);
1102b1b0d66SAndy Shevchenko 		int lo = hex_to_bin(uuid[si[i]] + 1);
1112b1b0d66SAndy Shevchenko 
1122b1b0d66SAndy Shevchenko 		b[ei[i]] = (hi << 4) | lo;
1132b1b0d66SAndy Shevchenko 	}
1142b1b0d66SAndy Shevchenko 
1152b1b0d66SAndy Shevchenko 	return 0;
1162b1b0d66SAndy Shevchenko }
1172b1b0d66SAndy Shevchenko 
1182b1b0d66SAndy Shevchenko int uuid_le_to_bin(const char *uuid, uuid_le *u)
1192b1b0d66SAndy Shevchenko {
1202b1b0d66SAndy Shevchenko 	return __uuid_to_bin(uuid, u->b, uuid_le_index);
1212b1b0d66SAndy Shevchenko }
1222b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_le_to_bin);
1232b1b0d66SAndy Shevchenko 
1242b1b0d66SAndy Shevchenko int uuid_be_to_bin(const char *uuid, uuid_be *u)
1252b1b0d66SAndy Shevchenko {
1262b1b0d66SAndy Shevchenko 	return __uuid_to_bin(uuid, u->b, uuid_be_index);
1272b1b0d66SAndy Shevchenko }
1282b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_be_to_bin);
129