xref: /spdk/lib/util/uuid.c (revision 12fbe739a31b09aff0d05f354d4f3bbef99afc55)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/uuid.h"
7 #include "spdk/config.h"
8 #include "spdk/log.h"
9 
10 #ifndef SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1
11 #include <openssl/evp.h>
12 #endif /* SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 */
13 
14 #ifndef __FreeBSD__
15 
16 #include <uuid/uuid.h>
17 
18 SPDK_STATIC_ASSERT(sizeof(struct spdk_uuid) == sizeof(uuid_t), "Size mismatch");
19 
20 int
21 spdk_uuid_parse(struct spdk_uuid *uuid, const char *uuid_str)
22 {
23 	return uuid_parse(uuid_str, (void *)uuid) == 0 ? 0 : -EINVAL;
24 }
25 
26 int
27 spdk_uuid_fmt_lower(char *uuid_str, size_t uuid_str_size, const struct spdk_uuid *uuid)
28 {
29 	if (uuid_str_size < SPDK_UUID_STRING_LEN) {
30 		return -EINVAL;
31 	}
32 
33 	uuid_unparse_lower((void *)uuid, uuid_str);
34 	return 0;
35 }
36 
37 int
38 spdk_uuid_compare(const struct spdk_uuid *u1, const struct spdk_uuid *u2)
39 {
40 	return uuid_compare((void *)u1, (void *)u2);
41 }
42 
43 void
44 spdk_uuid_generate(struct spdk_uuid *uuid)
45 {
46 	uuid_generate((void *)uuid);
47 }
48 
49 void
50 spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src)
51 {
52 	uuid_copy((void *)dst, (void *)src);
53 }
54 
55 bool
56 spdk_uuid_is_null(const struct spdk_uuid *uuid)
57 {
58 	return uuid_is_null((void *)uuid);
59 }
60 
61 void
62 spdk_uuid_set_null(struct spdk_uuid *uuid)
63 {
64 	uuid_clear((void *)uuid);
65 }
66 
67 #else
68 
69 #include <uuid.h>
70 
71 SPDK_STATIC_ASSERT(sizeof(struct spdk_uuid) == sizeof(uuid_t), "Size mismatch");
72 
73 int
74 spdk_uuid_parse(struct spdk_uuid *uuid, const char *uuid_str)
75 {
76 	uint32_t status;
77 
78 	uuid_from_string(uuid_str, (uuid_t *)uuid, &status);
79 
80 	return status == 0 ? 0 : -EINVAL;
81 }
82 
83 int
84 spdk_uuid_fmt_lower(char *uuid_str, size_t uuid_str_size, const struct spdk_uuid *uuid)
85 {
86 	uint32_t status;
87 	char *str;
88 
89 	if (uuid_str_size < SPDK_UUID_STRING_LEN) {
90 		return -EINVAL;
91 	}
92 
93 	uuid_to_string((const uuid_t *)uuid, &str, &status);
94 
95 	if (status == uuid_s_no_memory) {
96 		return -ENOMEM;
97 	}
98 
99 	snprintf(uuid_str, uuid_str_size, "%s", str);
100 	free(str);
101 
102 	return 0;
103 }
104 
105 int
106 spdk_uuid_compare(const struct spdk_uuid *u1, const struct spdk_uuid *u2)
107 {
108 	return uuid_compare((const uuid_t *)u1, (const uuid_t *)u2, NULL);
109 }
110 
111 void
112 spdk_uuid_generate(struct spdk_uuid *uuid)
113 {
114 	uuid_create((uuid_t *)uuid, NULL);
115 }
116 
117 void
118 spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src)
119 {
120 	memcpy(dst, src, sizeof(*dst));
121 }
122 
123 bool
124 spdk_uuid_is_null(const struct spdk_uuid *uuid)
125 {
126 	return uuid_is_nil((const uuid_t *)uuid, NULL);
127 }
128 
129 void
130 spdk_uuid_set_null(struct spdk_uuid *uuid)
131 {
132 	uuid_create_nil((uuid_t *)uuid, NULL);
133 }
134 
135 #endif
136 
137 int
138 spdk_uuid_generate_sha1(struct spdk_uuid *uuid, struct spdk_uuid *ns_uuid, const char *name,
139 			size_t len)
140 {
141 #ifdef SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1
142 	uuid_generate_sha1((void *)uuid, (void *)ns_uuid, name, len);
143 	return 0;
144 #else
145 	EVP_MD_CTX *mdctx;
146 	const EVP_MD *md;
147 	unsigned char md_value[EVP_MAX_MD_SIZE];
148 	unsigned int md_len;
149 
150 	md = EVP_sha1();
151 	assert(md != NULL);
152 
153 	mdctx = EVP_MD_CTX_new();
154 	if (mdctx == NULL) {
155 		return -ENOMEM;
156 	}
157 
158 	if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) {
159 		SPDK_ERRLOG("Could not initialize EVP digest!\n");
160 		goto err;
161 	}
162 	if (EVP_DigestUpdate(mdctx, ns_uuid, sizeof(struct spdk_uuid)) != 1) {
163 		SPDK_ERRLOG("Could update EVP digest with namespace UUID!\n");
164 		goto err;
165 	}
166 	if (EVP_DigestUpdate(mdctx, name, len) != 1) {
167 		SPDK_ERRLOG("Could update EVP digest with assigned name!\n");
168 		goto err;
169 	}
170 	if (EVP_DigestFinal_ex(mdctx, md_value, &md_len) != 1) {
171 		SPDK_ERRLOG("Could not generate EVP digest!\n");
172 		goto err;
173 	}
174 	EVP_MD_CTX_free(mdctx);
175 
176 	memcpy(uuid, md_value, 16);
177 	/* This part mimics original uuid_generate_sha1() from libuuid/src/gen_uuid.c.
178 	 * The original uuid structure included from uuid.h looks like this:
179 	 * struct uuid {
180 	 *	uint32_t	time_low;
181 	 *	uint16_t	time_mid;
182 	 *	uint16_t	time_hi_and_version;
183 	 *	uint16_t	clock_seq;
184 	 *	uint8_t		node[6];
185 	 * };
186 	 * so uuid->u.raw[6] and uuid->u.raw[8] are time_hi_and_version and clock_seq respectively.
187 	 */
188 	uuid->u.raw[6] = (uuid->u.raw[6] & 0x0f) | 0x50;
189 	uuid->u.raw[8] = (uuid->u.raw[8] & 0x3f) | 0x80;
190 
191 	return 0;
192 
193 err:
194 	EVP_MD_CTX_free(mdctx);
195 	return -EINVAL;
196 
197 #endif /* SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 */
198 }
199