xref: /openbmc/linux/lib/uuid.c (revision 2b1b0d66704a8cafe83be7114ec4c15ab3a314ad)
1fab1c232SHuang Ying /*
2fab1c232SHuang Ying  * Unified UUID/GUID definition
3fab1c232SHuang Ying  *
4fab1c232SHuang Ying  * Copyright (C) 2009, 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  * You should have received a copy of the GNU General Public License
17fab1c232SHuang Ying  * along with this program; if not, write to the Free Software
18fab1c232SHuang Ying  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19fab1c232SHuang Ying  */
20fab1c232SHuang Ying 
21fab1c232SHuang Ying #include <linux/kernel.h>
22*2b1b0d66SAndy Shevchenko #include <linux/ctype.h>
23*2b1b0d66SAndy Shevchenko #include <linux/errno.h>
248bc3bcc9SPaul Gortmaker #include <linux/export.h>
25fab1c232SHuang Ying #include <linux/uuid.h>
26fab1c232SHuang Ying #include <linux/random.h>
27fab1c232SHuang Ying 
28*2b1b0d66SAndy Shevchenko const u8 uuid_le_index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
29*2b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_le_index);
30*2b1b0d66SAndy Shevchenko const u8 uuid_be_index[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
31*2b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_be_index);
32*2b1b0d66SAndy Shevchenko 
338da4b8c4SAndy Shevchenko /***************************************************************
348da4b8c4SAndy Shevchenko  * Random UUID interface
358da4b8c4SAndy Shevchenko  *
368da4b8c4SAndy Shevchenko  * Used here for a Boot ID, but can be useful for other kernel
378da4b8c4SAndy Shevchenko  * drivers.
388da4b8c4SAndy Shevchenko  ***************************************************************/
398da4b8c4SAndy Shevchenko 
408da4b8c4SAndy Shevchenko /*
418da4b8c4SAndy Shevchenko  * Generate random UUID
428da4b8c4SAndy Shevchenko  */
438da4b8c4SAndy Shevchenko void generate_random_uuid(unsigned char uuid[16])
448da4b8c4SAndy Shevchenko {
458da4b8c4SAndy Shevchenko 	get_random_bytes(uuid, 16);
468da4b8c4SAndy Shevchenko 	/* Set UUID version to 4 --- truly random generation */
478da4b8c4SAndy Shevchenko 	uuid[6] = (uuid[6] & 0x0F) | 0x40;
488da4b8c4SAndy Shevchenko 	/* Set the UUID variant to DCE */
498da4b8c4SAndy Shevchenko 	uuid[8] = (uuid[8] & 0x3F) | 0x80;
508da4b8c4SAndy Shevchenko }
518da4b8c4SAndy Shevchenko EXPORT_SYMBOL(generate_random_uuid);
528da4b8c4SAndy Shevchenko 
53fab1c232SHuang Ying static void __uuid_gen_common(__u8 b[16])
54fab1c232SHuang Ying {
55cedddb00SAkinobu Mita 	prandom_bytes(b, 16);
56fab1c232SHuang Ying 	/* reversion 0b10 */
57fab1c232SHuang Ying 	b[8] = (b[8] & 0x3F) | 0x80;
58fab1c232SHuang Ying }
59fab1c232SHuang Ying 
60fab1c232SHuang Ying void uuid_le_gen(uuid_le *lu)
61fab1c232SHuang Ying {
62fab1c232SHuang Ying 	__uuid_gen_common(lu->b);
63fab1c232SHuang Ying 	/* version 4 : random generation */
64fab1c232SHuang Ying 	lu->b[7] = (lu->b[7] & 0x0F) | 0x40;
65fab1c232SHuang Ying }
66fab1c232SHuang Ying EXPORT_SYMBOL_GPL(uuid_le_gen);
67fab1c232SHuang Ying 
68fab1c232SHuang Ying void uuid_be_gen(uuid_be *bu)
69fab1c232SHuang Ying {
70fab1c232SHuang Ying 	__uuid_gen_common(bu->b);
71fab1c232SHuang Ying 	/* version 4 : random generation */
72fab1c232SHuang Ying 	bu->b[6] = (bu->b[6] & 0x0F) | 0x40;
73fab1c232SHuang Ying }
74fab1c232SHuang Ying EXPORT_SYMBOL_GPL(uuid_be_gen);
75*2b1b0d66SAndy Shevchenko 
76*2b1b0d66SAndy Shevchenko /**
77*2b1b0d66SAndy Shevchenko   * uuid_is_valid - checks if UUID string valid
78*2b1b0d66SAndy Shevchenko   * @uuid:	UUID string to check
79*2b1b0d66SAndy Shevchenko   *
80*2b1b0d66SAndy Shevchenko   * Description:
81*2b1b0d66SAndy Shevchenko   * It checks if the UUID string is following the format:
82*2b1b0d66SAndy Shevchenko   *	xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
83*2b1b0d66SAndy Shevchenko   * where x is a hex digit.
84*2b1b0d66SAndy Shevchenko   *
85*2b1b0d66SAndy Shevchenko   * Return: true if input is valid UUID string.
86*2b1b0d66SAndy Shevchenko   */
87*2b1b0d66SAndy Shevchenko bool uuid_is_valid(const char *uuid)
88*2b1b0d66SAndy Shevchenko {
89*2b1b0d66SAndy Shevchenko 	unsigned int i;
90*2b1b0d66SAndy Shevchenko 
91*2b1b0d66SAndy Shevchenko 	for (i = 0; i < UUID_STRING_LEN; i++) {
92*2b1b0d66SAndy Shevchenko 		if (i == 8 || i == 13 || i == 18 || i == 23) {
93*2b1b0d66SAndy Shevchenko 			if (uuid[i] != '-')
94*2b1b0d66SAndy Shevchenko 				return false;
95*2b1b0d66SAndy Shevchenko 		} else if (!isxdigit(uuid[i])) {
96*2b1b0d66SAndy Shevchenko 			return false;
97*2b1b0d66SAndy Shevchenko 		}
98*2b1b0d66SAndy Shevchenko 	}
99*2b1b0d66SAndy Shevchenko 
100*2b1b0d66SAndy Shevchenko 	return true;
101*2b1b0d66SAndy Shevchenko }
102*2b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_is_valid);
103*2b1b0d66SAndy Shevchenko 
104*2b1b0d66SAndy Shevchenko static int __uuid_to_bin(const char *uuid, __u8 b[16], const u8 ei[16])
105*2b1b0d66SAndy Shevchenko {
106*2b1b0d66SAndy Shevchenko 	static const u8 si[16] = {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34};
107*2b1b0d66SAndy Shevchenko 	unsigned int i;
108*2b1b0d66SAndy Shevchenko 
109*2b1b0d66SAndy Shevchenko 	if (!uuid_is_valid(uuid))
110*2b1b0d66SAndy Shevchenko 		return -EINVAL;
111*2b1b0d66SAndy Shevchenko 
112*2b1b0d66SAndy Shevchenko 	for (i = 0; i < 16; i++) {
113*2b1b0d66SAndy Shevchenko 		int hi = hex_to_bin(uuid[si[i]] + 0);
114*2b1b0d66SAndy Shevchenko 		int lo = hex_to_bin(uuid[si[i]] + 1);
115*2b1b0d66SAndy Shevchenko 
116*2b1b0d66SAndy Shevchenko 		b[ei[i]] = (hi << 4) | lo;
117*2b1b0d66SAndy Shevchenko 	}
118*2b1b0d66SAndy Shevchenko 
119*2b1b0d66SAndy Shevchenko 	return 0;
120*2b1b0d66SAndy Shevchenko }
121*2b1b0d66SAndy Shevchenko 
122*2b1b0d66SAndy Shevchenko int uuid_le_to_bin(const char *uuid, uuid_le *u)
123*2b1b0d66SAndy Shevchenko {
124*2b1b0d66SAndy Shevchenko 	return __uuid_to_bin(uuid, u->b, uuid_le_index);
125*2b1b0d66SAndy Shevchenko }
126*2b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_le_to_bin);
127*2b1b0d66SAndy Shevchenko 
128*2b1b0d66SAndy Shevchenko int uuid_be_to_bin(const char *uuid, uuid_be *u)
129*2b1b0d66SAndy Shevchenko {
130*2b1b0d66SAndy Shevchenko 	return __uuid_to_bin(uuid, u->b, uuid_be_index);
131*2b1b0d66SAndy Shevchenko }
132*2b1b0d66SAndy Shevchenko EXPORT_SYMBOL(uuid_be_to_bin);
133