162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Unified UUID/GUID definition 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009, 2016 Intel Corp. 662306a36Sopenharmony_ci * Huang Ying <ying.huang@intel.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/ctype.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/export.h> 1362306a36Sopenharmony_ci#include <linux/uuid.h> 1462306a36Sopenharmony_ci#include <linux/random.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciconst guid_t guid_null; 1762306a36Sopenharmony_ciEXPORT_SYMBOL(guid_null); 1862306a36Sopenharmony_ciconst uuid_t uuid_null; 1962306a36Sopenharmony_ciEXPORT_SYMBOL(uuid_null); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciconst u8 guid_index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; 2262306a36Sopenharmony_ciconst u8 uuid_index[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/** 2562306a36Sopenharmony_ci * generate_random_uuid - generate a random UUID 2662306a36Sopenharmony_ci * @uuid: where to put the generated UUID 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * Random UUID interface 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * Used to create a Boot ID or a filesystem UUID/GUID, but can be 3162306a36Sopenharmony_ci * useful for other kernel drivers. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_civoid generate_random_uuid(unsigned char uuid[16]) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci get_random_bytes(uuid, 16); 3662306a36Sopenharmony_ci /* Set UUID version to 4 --- truly random generation */ 3762306a36Sopenharmony_ci uuid[6] = (uuid[6] & 0x0F) | 0x40; 3862306a36Sopenharmony_ci /* Set the UUID variant to DCE */ 3962306a36Sopenharmony_ci uuid[8] = (uuid[8] & 0x3F) | 0x80; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ciEXPORT_SYMBOL(generate_random_uuid); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_civoid generate_random_guid(unsigned char guid[16]) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci get_random_bytes(guid, 16); 4662306a36Sopenharmony_ci /* Set GUID version to 4 --- truly random generation */ 4762306a36Sopenharmony_ci guid[7] = (guid[7] & 0x0F) | 0x40; 4862306a36Sopenharmony_ci /* Set the GUID variant to DCE */ 4962306a36Sopenharmony_ci guid[8] = (guid[8] & 0x3F) | 0x80; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ciEXPORT_SYMBOL(generate_random_guid); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic void __uuid_gen_common(__u8 b[16]) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci get_random_bytes(b, 16); 5662306a36Sopenharmony_ci /* reversion 0b10 */ 5762306a36Sopenharmony_ci b[8] = (b[8] & 0x3F) | 0x80; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_civoid guid_gen(guid_t *lu) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci __uuid_gen_common(lu->b); 6362306a36Sopenharmony_ci /* version 4 : random generation */ 6462306a36Sopenharmony_ci lu->b[7] = (lu->b[7] & 0x0F) | 0x40; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(guid_gen); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_civoid uuid_gen(uuid_t *bu) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci __uuid_gen_common(bu->b); 7162306a36Sopenharmony_ci /* version 4 : random generation */ 7262306a36Sopenharmony_ci bu->b[6] = (bu->b[6] & 0x0F) | 0x40; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(uuid_gen); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/** 7762306a36Sopenharmony_ci * uuid_is_valid - checks if a UUID string is valid 7862306a36Sopenharmony_ci * @uuid: UUID string to check 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * Description: 8162306a36Sopenharmony_ci * It checks if the UUID string is following the format: 8262306a36Sopenharmony_ci * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * where x is a hex digit. 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * Return: true if input is valid UUID string. 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cibool uuid_is_valid(const char *uuid) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci unsigned int i; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci for (i = 0; i < UUID_STRING_LEN; i++) { 9362306a36Sopenharmony_ci if (i == 8 || i == 13 || i == 18 || i == 23) { 9462306a36Sopenharmony_ci if (uuid[i] != '-') 9562306a36Sopenharmony_ci return false; 9662306a36Sopenharmony_ci } else if (!isxdigit(uuid[i])) { 9762306a36Sopenharmony_ci return false; 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci return true; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ciEXPORT_SYMBOL(uuid_is_valid); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic int __uuid_parse(const char *uuid, __u8 b[16], const u8 ei[16]) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci static const u8 si[16] = {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34}; 10862306a36Sopenharmony_ci unsigned int i; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (!uuid_is_valid(uuid)) 11162306a36Sopenharmony_ci return -EINVAL; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci for (i = 0; i < 16; i++) { 11462306a36Sopenharmony_ci int hi = hex_to_bin(uuid[si[i] + 0]); 11562306a36Sopenharmony_ci int lo = hex_to_bin(uuid[si[i] + 1]); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci b[ei[i]] = (hi << 4) | lo; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return 0; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciint guid_parse(const char *uuid, guid_t *u) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci return __uuid_parse(uuid, u->b, guid_index); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ciEXPORT_SYMBOL(guid_parse); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ciint uuid_parse(const char *uuid, uuid_t *u) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci return __uuid_parse(uuid, u->b, uuid_index); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ciEXPORT_SYMBOL(uuid_parse); 134