// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #ifdef OPENSSL_FOUND #include #endif #include #include #include #include #include "xtest_uuid_helpers.h" static int hex(char c) { char lc = tolower(c); if (isdigit(lc)) return lc - '0'; if (isxdigit(lc)) return lc - 'a' + 10; return -1; } static uint32_t parse_hex(const char *s, size_t nchars, uint32_t *res) { uint32_t v = 0; size_t n = 0; int c = 0; for (n = 0; n < nchars; n++) { c = hex(s[n]); if (c == -1) { *res = TEE_ERROR_BAD_FORMAT; goto out; } v = (v << 4) + c; } *res = TEE_SUCCESS; out: return v; } TEEC_Result xtest_uuid_from_str(TEEC_UUID *uuid, const char *s) { TEEC_Result res = TEEC_SUCCESS; TEEC_UUID u = { }; const char *p = s; size_t i = 0; if (!p || strnlen(p, 37) != 36) return TEEC_ERROR_BAD_FORMAT; if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-') return TEEC_ERROR_BAD_FORMAT; u.timeLow = parse_hex(p, 8, &res); if (res) goto out; p += 9; u.timeMid = parse_hex(p, 4, &res); if (res) goto out; p += 5; u.timeHiAndVersion = parse_hex(p, 4, &res); if (res) goto out; p += 5; for (i = 0; i < 8; i++) { u.clockSeqAndNode[i] = parse_hex(p, 2, &res); if (res) goto out; if (i == 1) p += 3; else p += 2; } *uuid = u; out: return res; } #ifdef OPENSSL_FOUND TEEC_Result xtest_uuid_v5(TEEC_UUID *uuid, const TEEC_UUID *ns, const void *name, size_t size) { TEEC_Result res = TEEC_SUCCESS; EVP_MD_CTX *mdctx = NULL; const EVP_MD *md = NULL; unsigned char hash[EVP_MAX_MD_SIZE] = { }; unsigned int md_len = 0; unsigned char nsbe[16] = { }; uint32_t be32 = 0; uint16_t be16 = 0; int ret = 0; /* Convert from host to big endian */ be32 = htobe32(ns->timeLow); memcpy(&nsbe[0], &be32, sizeof(be32)); be16 = htobe16(ns->timeMid); memcpy(&nsbe[4], &be16, sizeof(be16)); be16 = htobe16(ns->timeHiAndVersion); memcpy(&nsbe[6], &be16, sizeof(be16)); memcpy(&nsbe[8], &ns->clockSeqAndNode, sizeof(ns->clockSeqAndNode)); mdctx = EVP_MD_CTX_create(); if (!mdctx) return TEEC_ERROR_OUT_OF_MEMORY; md = EVP_sha1(); if (!md) { res = TEEC_ERROR_NOT_SUPPORTED; goto out; } ret = EVP_DigestInit_ex(mdctx, md, NULL); if (!ret) { res = TEEC_ERROR_GENERIC; goto out; } ret = EVP_DigestUpdate(mdctx, nsbe, sizeof(nsbe)); if (!ret) { res = TEEC_ERROR_GENERIC; goto out; } ret = EVP_DigestUpdate(mdctx, name, size); if (!ret) { res = TEEC_ERROR_GENERIC; goto out; } ret = EVP_DigestFinal_ex(mdctx, hash, &md_len); if (!ret) { res = TEEC_ERROR_GENERIC; goto out; } /* Mark it as UUIDv5 */ hash[6] = (hash[6] & 0x0F) | 0x50; hash[8] = (hash[8] & 0x3F) | 0x80; /* Convert from big endian to host */ memcpy(&be32, &hash[0], sizeof(uint32_t)); uuid->timeLow = be32toh(be32); memcpy(&be16, &hash[4], sizeof(uint16_t)); uuid->timeMid = be16toh(be16); memcpy(&be16, &hash[6], sizeof(uint16_t)); uuid->timeHiAndVersion = be16toh(be16); memcpy(uuid->clockSeqAndNode, &hash[8], sizeof(uuid->clockSeqAndNode)); out: EVP_MD_CTX_destroy(mdctx); return res; } #endif /*OPENSSL_FOUND*/