xref: /spdk/lib/util/uuid.c (revision a0d24145bf3d795cf89adc414320b138fae480ab)
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 #else
56 
57 #include <uuid.h>
58 
59 SPDK_STATIC_ASSERT(sizeof(struct spdk_uuid) == sizeof(uuid_t), "Size mismatch");
60 
61 int
62 spdk_uuid_parse(struct spdk_uuid *uuid, const char *uuid_str)
63 {
64 	uint32_t status;
65 
66 	uuid_from_string(uuid_str, (uuid_t *)uuid, &status);
67 
68 	return status == 0 ? 0 : -EINVAL;
69 }
70 
71 int
72 spdk_uuid_fmt_lower(char *uuid_str, size_t uuid_str_size, const struct spdk_uuid *uuid)
73 {
74 	uint32_t status;
75 	char *str;
76 
77 	if (uuid_str_size < SPDK_UUID_STRING_LEN) {
78 		return -EINVAL;
79 	}
80 
81 	uuid_to_string((const uuid_t *)uuid, &str, &status);
82 
83 	if (status == uuid_s_no_memory) {
84 		return -ENOMEM;
85 	}
86 
87 	snprintf(uuid_str, uuid_str_size, "%s", str);
88 	free(str);
89 
90 	return 0;
91 }
92 
93 int
94 spdk_uuid_compare(const struct spdk_uuid *u1, const struct spdk_uuid *u2)
95 {
96 	return uuid_compare((const uuid_t *)u1, (const uuid_t *)u2, NULL);
97 }
98 
99 void
100 spdk_uuid_generate(struct spdk_uuid *uuid)
101 {
102 	uuid_create((uuid_t *)uuid, NULL);
103 }
104 
105 void
106 spdk_uuid_copy(struct spdk_uuid *dst, const struct spdk_uuid *src)
107 {
108 	memcpy(dst, src, sizeof(*dst));
109 }
110 
111 #endif
112 
113 int
114 spdk_uuid_generate_sha1(struct spdk_uuid *uuid, struct spdk_uuid *ns_uuid, const char *name,
115 			size_t len)
116 {
117 #ifdef SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1
118 	uuid_generate_sha1((void *)uuid, (void *)ns_uuid, name, len);
119 	return 0;
120 #else
121 	EVP_MD_CTX *mdctx;
122 	const EVP_MD *md;
123 	unsigned char md_value[EVP_MAX_MD_SIZE];
124 	unsigned int md_len;
125 
126 	md = EVP_sha1();
127 	assert(md != NULL);
128 
129 	mdctx = EVP_MD_CTX_new();
130 	if (mdctx == NULL) {
131 		return -ENOMEM;
132 	}
133 
134 	if (EVP_DigestInit_ex(mdctx, md, NULL) != 1) {
135 		SPDK_ERRLOG("Could not initialize EVP digest!\n");
136 		goto err;
137 	}
138 	if (EVP_DigestUpdate(mdctx, ns_uuid, sizeof(struct spdk_uuid)) != 1) {
139 		SPDK_ERRLOG("Could update EVP digest with namespace UUID!\n");
140 		goto err;
141 	}
142 	if (EVP_DigestUpdate(mdctx, name, len) != 1) {
143 		SPDK_ERRLOG("Could update EVP digest with assigned name!\n");
144 		goto err;
145 	}
146 	if (EVP_DigestFinal_ex(mdctx, md_value, &md_len) != 1) {
147 		SPDK_ERRLOG("Could not generate EVP digest!\n");
148 		goto err;
149 	}
150 	EVP_MD_CTX_free(mdctx);
151 
152 	memcpy(uuid, md_value, 16);
153 	/* This part mimics original uuid_generate_sha1() from libuuid/src/gen_uuid.c.
154 	 * The original uuid structure included from uuid.h looks like this:
155 	 * struct uuid {
156 	 *	uint32_t	time_low;
157 	 *	uint16_t	time_mid;
158 	 *	uint16_t	time_hi_and_version;
159 	 *	uint16_t	clock_seq;
160 	 *	uint8_t		node[6];
161 	 * };
162 	 * so uuid->u.raw[6] and uuid->u.raw[8] are time_hi_and_version and clock_seq respectively.
163 	 */
164 	uuid->u.raw[6] = (uuid->u.raw[6] & 0x0f) | 0x50;
165 	uuid->u.raw[8] = (uuid->u.raw[8] & 0x3f) | 0x80;
166 
167 	return 0;
168 
169 err:
170 	EVP_MD_CTX_free(mdctx);
171 	return -EINVAL;
172 
173 #endif /* SPDK_CONFIG_HAVE_UUID_GENERATE_SHA1 */
174 }
175