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