xref: /aosp_15_r20/external/erofs-utils/lib/uuid.c (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker  * Copyright (C) 2023 Norbert Lange <[email protected]>
4*33b1fccfSAndroid Build Coastguard Worker  */
5*33b1fccfSAndroid Build Coastguard Worker 
6*33b1fccfSAndroid Build Coastguard Worker #include <string.h>
7*33b1fccfSAndroid Build Coastguard Worker #include <errno.h>
8*33b1fccfSAndroid Build Coastguard Worker 
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/config.h"
10*33b1fccfSAndroid Build Coastguard Worker #include "erofs/defs.h"
11*33b1fccfSAndroid Build Coastguard Worker #include "liberofs_uuid.h"
12*33b1fccfSAndroid Build Coastguard Worker 
13*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBUUID
14*33b1fccfSAndroid Build Coastguard Worker #include <uuid.h>
15*33b1fccfSAndroid Build Coastguard Worker #else
16*33b1fccfSAndroid Build Coastguard Worker 
17*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
18*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_SYS_RANDOM_H
19*33b1fccfSAndroid Build Coastguard Worker #include <sys/random.h>
20*33b1fccfSAndroid Build Coastguard Worker #else
21*33b1fccfSAndroid Build Coastguard Worker #define _GNU_SOURCE
22*33b1fccfSAndroid Build Coastguard Worker #include <unistd.h>
23*33b1fccfSAndroid Build Coastguard Worker #include <sys/syscall.h>
24*33b1fccfSAndroid Build Coastguard Worker #endif
25*33b1fccfSAndroid Build Coastguard Worker 
26*33b1fccfSAndroid Build Coastguard Worker /* Flags to be used, will be modified if kernel does not support them */
27*33b1fccfSAndroid Build Coastguard Worker static unsigned int erofs_grnd_flag =
28*33b1fccfSAndroid Build Coastguard Worker #ifdef GRND_INSECURE
29*33b1fccfSAndroid Build Coastguard Worker 	GRND_INSECURE;
30*33b1fccfSAndroid Build Coastguard Worker #else
31*33b1fccfSAndroid Build Coastguard Worker 	0x0004;
32*33b1fccfSAndroid Build Coastguard Worker #endif
33*33b1fccfSAndroid Build Coastguard Worker 
s_getrandom(void * out,unsigned size,bool insecure)34*33b1fccfSAndroid Build Coastguard Worker static int s_getrandom(void *out, unsigned size, bool insecure)
35*33b1fccfSAndroid Build Coastguard Worker {
36*33b1fccfSAndroid Build Coastguard Worker 	unsigned int kflags = erofs_grnd_flag;
37*33b1fccfSAndroid Build Coastguard Worker 	unsigned int flags = insecure ? kflags : 0;
38*33b1fccfSAndroid Build Coastguard Worker 
39*33b1fccfSAndroid Build Coastguard Worker 	for (;;)
40*33b1fccfSAndroid Build Coastguard Worker 	{
41*33b1fccfSAndroid Build Coastguard Worker 		ssize_t r;
42*33b1fccfSAndroid Build Coastguard Worker 		int err;
43*33b1fccfSAndroid Build Coastguard Worker 
44*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_SYS_RANDOM_H
45*33b1fccfSAndroid Build Coastguard Worker 		r = getrandom(out, size, flags);
46*33b1fccfSAndroid Build Coastguard Worker #elif defined(__NR_getrandom)
47*33b1fccfSAndroid Build Coastguard Worker 		r = (ssize_t)syscall(__NR_getrandom, out, size, flags);
48*33b1fccfSAndroid Build Coastguard Worker #else
49*33b1fccfSAndroid Build Coastguard Worker 		r = -1;
50*33b1fccfSAndroid Build Coastguard Worker 		errno = ENOSYS;
51*33b1fccfSAndroid Build Coastguard Worker 		(void)flags;
52*33b1fccfSAndroid Build Coastguard Worker #endif
53*33b1fccfSAndroid Build Coastguard Worker 
54*33b1fccfSAndroid Build Coastguard Worker 		if (r == size)
55*33b1fccfSAndroid Build Coastguard Worker 			break;
56*33b1fccfSAndroid Build Coastguard Worker 		err = errno;
57*33b1fccfSAndroid Build Coastguard Worker 		if (err != EINTR) {
58*33b1fccfSAndroid Build Coastguard Worker 			if (__erofs_unlikely(err == ENOSYS && insecure)) {
59*33b1fccfSAndroid Build Coastguard Worker 				while (size) {
60*33b1fccfSAndroid Build Coastguard Worker 					*(u8 *)out++ = rand() % 256;
61*33b1fccfSAndroid Build Coastguard Worker 					--size;
62*33b1fccfSAndroid Build Coastguard Worker 				}
63*33b1fccfSAndroid Build Coastguard Worker 				err = 0;
64*33b1fccfSAndroid Build Coastguard Worker 			} else if (err == EINVAL && kflags) {
65*33b1fccfSAndroid Build Coastguard Worker 				// Kernel likely does not support GRND_INSECURE
66*33b1fccfSAndroid Build Coastguard Worker 				erofs_grnd_flag = 0;
67*33b1fccfSAndroid Build Coastguard Worker 				kflags = 0;
68*33b1fccfSAndroid Build Coastguard Worker 				continue;
69*33b1fccfSAndroid Build Coastguard Worker 			}
70*33b1fccfSAndroid Build Coastguard Worker 			return -err;
71*33b1fccfSAndroid Build Coastguard Worker 		}
72*33b1fccfSAndroid Build Coastguard Worker 	}
73*33b1fccfSAndroid Build Coastguard Worker 	return 0;
74*33b1fccfSAndroid Build Coastguard Worker }
75*33b1fccfSAndroid Build Coastguard Worker #endif
76*33b1fccfSAndroid Build Coastguard Worker 
erofs_uuid_generate(unsigned char * out)77*33b1fccfSAndroid Build Coastguard Worker void erofs_uuid_generate(unsigned char *out)
78*33b1fccfSAndroid Build Coastguard Worker {
79*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBUUID
80*33b1fccfSAndroid Build Coastguard Worker 	uuid_t new_uuid;
81*33b1fccfSAndroid Build Coastguard Worker 
82*33b1fccfSAndroid Build Coastguard Worker 	do {
83*33b1fccfSAndroid Build Coastguard Worker 		uuid_generate(new_uuid);
84*33b1fccfSAndroid Build Coastguard Worker 	} while (uuid_is_null(new_uuid));
85*33b1fccfSAndroid Build Coastguard Worker #else
86*33b1fccfSAndroid Build Coastguard Worker 	unsigned char new_uuid[16];
87*33b1fccfSAndroid Build Coastguard Worker 	int res __maybe_unused;
88*33b1fccfSAndroid Build Coastguard Worker 
89*33b1fccfSAndroid Build Coastguard Worker 	res = s_getrandom(new_uuid, sizeof(new_uuid), true);
90*33b1fccfSAndroid Build Coastguard Worker 	BUG_ON(res != 0);
91*33b1fccfSAndroid Build Coastguard Worker 
92*33b1fccfSAndroid Build Coastguard Worker 	// UID type + version bits
93*33b1fccfSAndroid Build Coastguard Worker 	new_uuid[0] = (new_uuid[4 + 2] & 0x0f) | 0x40;
94*33b1fccfSAndroid Build Coastguard Worker 	new_uuid[1] = (new_uuid[4 + 2 + 2] & 0x3f) | 0x80;
95*33b1fccfSAndroid Build Coastguard Worker #endif
96*33b1fccfSAndroid Build Coastguard Worker 	memcpy(out, new_uuid, sizeof(new_uuid));
97*33b1fccfSAndroid Build Coastguard Worker }
98*33b1fccfSAndroid Build Coastguard Worker 
erofs_uuid_parse(const char * in,unsigned char * uu)99*33b1fccfSAndroid Build Coastguard Worker int erofs_uuid_parse(const char *in, unsigned char *uu) {
100*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBUUID
101*33b1fccfSAndroid Build Coastguard Worker 	return uuid_parse((char *)in, uu);
102*33b1fccfSAndroid Build Coastguard Worker #else
103*33b1fccfSAndroid Build Coastguard Worker 	unsigned char new_uuid[16];
104*33b1fccfSAndroid Build Coastguard Worker 	unsigned int hypens = ((1U << 3) | (1U << 5) | (1U << 7) | (1U << 9));
105*33b1fccfSAndroid Build Coastguard Worker 	int i;
106*33b1fccfSAndroid Build Coastguard Worker 
107*33b1fccfSAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(new_uuid); hypens >>= 1, i++)
108*33b1fccfSAndroid Build Coastguard Worker 	{
109*33b1fccfSAndroid Build Coastguard Worker 		char c[] = { in[0], in[1], '\0' };
110*33b1fccfSAndroid Build Coastguard Worker 		char* endptr = c;
111*33b1fccfSAndroid Build Coastguard Worker 		unsigned long val = strtoul(c, &endptr, 16);
112*33b1fccfSAndroid Build Coastguard Worker 
113*33b1fccfSAndroid Build Coastguard Worker 		if (endptr - c != 2)
114*33b1fccfSAndroid Build Coastguard Worker 			return -EINVAL;
115*33b1fccfSAndroid Build Coastguard Worker 
116*33b1fccfSAndroid Build Coastguard Worker 		in += 2;
117*33b1fccfSAndroid Build Coastguard Worker 
118*33b1fccfSAndroid Build Coastguard Worker 		if ((hypens & 1U) != 0) {
119*33b1fccfSAndroid Build Coastguard Worker 			if (*in++ != '-')
120*33b1fccfSAndroid Build Coastguard Worker 				return -EINVAL;
121*33b1fccfSAndroid Build Coastguard Worker 		}
122*33b1fccfSAndroid Build Coastguard Worker 		new_uuid[i] = (unsigned char)val;
123*33b1fccfSAndroid Build Coastguard Worker 	}
124*33b1fccfSAndroid Build Coastguard Worker 
125*33b1fccfSAndroid Build Coastguard Worker 	if (*in != '\0')
126*33b1fccfSAndroid Build Coastguard Worker 		return -EINVAL;
127*33b1fccfSAndroid Build Coastguard Worker 	memcpy(uu, new_uuid, sizeof(new_uuid));
128*33b1fccfSAndroid Build Coastguard Worker 	return 0;
129*33b1fccfSAndroid Build Coastguard Worker #endif
130*33b1fccfSAndroid Build Coastguard Worker }
131