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