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