From a094e6dd76031f973e78c1f2f3af0e9e1118439a Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Tue, 25 Feb 2025 15:41:56 +0200 Subject: [PATCH 01/18] MeTee: add TeeGetKind API Multiple device types could present on the platform. New API will help to distinguish between them. Signed-off-by: Abliyev, Reuven --- include/metee.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/metee.h b/include/metee.h index 43bea22..a345f64 100644 --- a/include/metee.h +++ b/include/metee.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ /*! \file metee.h * \brief metee library API @@ -347,6 +347,16 @@ uint32_t TEEAPI TeeGetMaxMsgLen(IN const PTEEHANDLE handle); */ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle); + +/*! Obtains kind of the TEE device + * \param handle The handle of the session. + * \param kind Buffer to fill with device kind null terminated string, may be NULL. + * \param kindSize Pointer to kind buffer size in bytes, updated to number of bytes filled in buffer, including null character, on out. + * If buffer is NULL, required size is returned anyway. + * \return 0 if successful, otherwise error code. + */ +TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize); + #ifdef __cplusplus } #endif From 3d640c4cee1f337e2f46d7b20eea42dab75a09cb Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Tue, 25 Feb 2025 15:47:49 +0200 Subject: [PATCH 02/18] MeTee: Windows: TeeGetKind implementation Implement TeeGetKind on Windows via WMI driver interface. Signed-off-by: Abliyev, Reuven --- src/Windows/metee_win.c | 26 +++++++ src/Windows/metee_win.h | 3 +- src/Windows/metee_winhelpers.c | 127 ++++++++++++++++++++++++++++++++- 3 files changed, 154 insertions(+), 2 deletions(-) diff --git a/src/Windows/metee_win.c b/src/Windows/metee_win.c index ac9a6c7..b4aeb58 100644 --- a/src/Windows/metee_win.c +++ b/src/Windows/metee_win.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "public.h" #include "helpers.h" @@ -696,3 +698,27 @@ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) } return handle->protcolVer; } + +TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) +{ + TEESTATUS status = TEE_INTERNAL_ERROR; + + if (NULL == handle) { + return TEE_INVALID_PARAMETER; + } + + struct METEE_WIN_IMPL* impl_handle = to_int(handle); + + FUNC_ENTRY(handle); + + if (NULL == impl_handle || NULL == kindSize) { + status = TEE_INVALID_PARAMETER; + ERRPRINT(handle, "One of the parameters was illegal"); + goto Cleanup; + } + status = GetDeviceKind(handle, kind, kindSize); + +Cleanup: + FUNC_EXIT(handle, status); + return status; +} diff --git a/src/Windows/metee_win.h b/src/Windows/metee_win.h index 5243e8f..9310613 100644 --- a/src/Windows/metee_win.h +++ b/src/Windows/metee_win.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ #ifndef __TEELIBWIN_H #define __TEELIBWIN_H @@ -54,6 +54,7 @@ TEESTATUS EndOverlapped(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD milli OUT OPTIONAL LPDWORD pNumberOfBytesTransferred); TEESTATUS GetDevicePath(IN PTEEHANDLE handle, IN LPCGUID InterfaceGuid, OUT char *path, IN SIZE_T pathSize); +TEESTATUS GetDeviceKind(IN PTEEHANDLE handle, IN OUT OPTIONAL char *kind, IN OUT size_t *kindSize); TEESTATUS SendIOCTL(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD ioControlCode, IN LPVOID pInBuffer, IN DWORD inBufferSize, IN LPVOID pOutBuffer, IN DWORD outBufferSize, OUT LPDWORD pBytesRetuned); diff --git a/src/Windows/metee_winhelpers.c b/src/Windows/metee_winhelpers.c index 912f6e3..854cd9b 100644 --- a/src/Windows/metee_winhelpers.c +++ b/src/Windows/metee_winhelpers.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ #include #include @@ -232,6 +232,131 @@ TEESTATUS GetDevicePath(IN PTEEHANDLE handle, IN LPCGUID InterfaceGuid, return status; } +DEFINE_DEVPROPKEY(DEVPKEY_TeedriverKindString, + 0x3279649a, 0x75b8, 0x4663, 0xab, 0x4f, 0x9d, 0xec, 0x58, 0xc5, 0x58, 0xf5, + DEVPROP_TYPE_STRING); +/* +** Get device kind implementation +** +** Parameters: +** handle - metee handle +** kind - pointer to hold device kind, null terminated C string +** kindSize - size in bytes allocated to kind including null terminator +** +** Return: +** TEE_SUCCESS +** TEE_INVALID_PARAMETER +** TEE_INTERNAL_ERROR +*/ +TEESTATUS GetDeviceKind(IN PTEEHANDLE handle, IN OUT OPTIONAL char *kind, IN OUT size_t *kindSize) +{ + CONFIGRET cr; + DEVPROPTYPE prop_type = 0; + ULONG prop_size = 0; + DEVINST devInstHandle; + WCHAR instance_id[MAX_PATH] = { 0 }; + WCHAR* device_path_w = NULL; + WCHAR* kind_w = NULL; + size_t converted_chars; + errno_t err; + + TEESTATUS status = TEE_INTERNAL_ERROR; + + if (NULL == handle) { + return TEE_INVALID_PARAMETER; + } + + struct METEE_WIN_IMPL* impl_handle = to_int(handle); + + FUNC_ENTRY(handle); + + size_t device_path_len = strlen(impl_handle->device_path) + 1; + size_t device_path_size = device_path_len * sizeof(WCHAR); + device_path_w = (WCHAR*)malloc(device_path_size); + if (NULL == device_path_w) { + status = TEE_INTERNAL_ERROR; + ERRPRINT(handle, "Error allocating memory for device path.\n"); + goto Cleanup; + } + converted_chars = 0; + mbstowcs_s(&converted_chars, device_path_w, device_path_len, impl_handle->device_path, _TRUNCATE); + if (converted_chars != device_path_len) { + status = TEE_INTERNAL_ERROR; + ERRPRINT(handle, "Error converting device path to wide.\n"); + goto Cleanup; + } + + prop_size = MAX_PATH; + cr = CM_Get_Device_Interface_PropertyW(device_path_w, &DEVPKEY_Device_InstanceId, &prop_type, (PBYTE)instance_id, &prop_size, 0); + if (cr != CR_SUCCESS) { + ERRPRINT(handle, "CM_Get_Device_Interface_Property: %d\n", cr); + status = TEE_INTERNAL_ERROR; + goto Cleanup; + } + if (DEVPROP_TYPE_STRING != prop_type) + { + ERRPRINT(handle, "Invalid property type %d\n", prop_type); + status = TEE_INTERNAL_ERROR; + goto Cleanup; + } + + cr = CM_Locate_DevNodeW(&devInstHandle, &instance_id[0], CM_LOCATE_DEVNODE_NORMAL); + if (cr != CR_SUCCESS) { + ERRPRINT(handle, "CM_Locate_DevNode: %d\n", cr); + status = TEE_INTERNAL_ERROR; + goto Cleanup; + } + + prop_size = 0; + cr = CM_Get_DevNode_PropertyW(devInstHandle, &DEVPKEY_TeedriverKindString, &prop_type, NULL, &prop_size, 0); + if (cr != CR_BUFFER_SMALL) { + ERRPRINT(handle, "CM_Get_DevNode_Property: %d %d\n", cr, prop_size); + status = TEE_INTERNAL_ERROR; + goto Cleanup; + } + kind_w = (WCHAR*)malloc(prop_size); + if (NULL == kind_w) { + status = TEE_INTERNAL_ERROR; + ERRPRINT(handle, "Error allocating memory for driver kind wide.\n"); + goto Cleanup; + } + cr = CM_Get_DevNode_PropertyW(devInstHandle, &DEVPKEY_TeedriverKindString, &prop_type, (PBYTE)kind_w, &prop_size, 0); + if (cr != CR_SUCCESS) { + ERRPRINT(handle, "CM_Get_DevNode_Property: %d %d\n", cr, prop_size); + status = TEE_INTERNAL_ERROR; + goto Cleanup; + } + if (*kindSize < prop_size) { + ERRPRINT(handle, "Insufficient buffer %d %d\n", *kindSize, prop_size); + *kindSize = prop_size; + status = TEE_INSUFFICIENT_BUFFER; + goto Cleanup; + } + /* + safe implementation of the conversion function + handles NULL input/output buffer values and output buffer overrun + */ + err = wcstombs_s(&converted_chars, kind, *kindSize, kind_w, _TRUNCATE); + if (err != 0) { + ERRPRINT(handle, "convert to multi-byte error %d\n", err); + if (err == STRUNCATE || err == EINVAL) { + *kindSize = prop_size; + status = TEE_INSUFFICIENT_BUFFER; + } else { + status = TEE_INTERNAL_ERROR; + } + goto Cleanup; + } + *kindSize = converted_chars; + status = TEE_SUCCESS; + +Cleanup: + free(kind_w); + free(device_path_w); + FUNC_EXIT(handle, status); + return status; +} + TEESTATUS SendIOCTL(IN PTEEHANDLE handle, IN EVENTHANDLE evt, IN DWORD ioControlCode, IN LPVOID pInBuffer, IN DWORD inBufferSize, IN LPVOID pOutBuffer, IN DWORD outBufferSize, OUT LPDWORD pBytesRetuned) From 225809dea0bb505505bf41e04844e1a1a24a53c8 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Wed, 26 Feb 2025 14:16:13 +0200 Subject: [PATCH 03/18] MeTee: samples: add TeeGetKind example Add example how to query device kind. Signed-off-by: Abliyev, Reuven --- samples/metee_basic.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/samples/metee_basic.c b/samples/metee_basic.c index 358051e..851fd19 100644 --- a/samples/metee_basic.c +++ b/samples/metee_basic.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation */ #include #include @@ -66,6 +66,8 @@ int main(int argc, char* argv[]) struct mkhi_fwver_req req; uint8_t *read_buf = NULL; struct mkhi_fwver_rsp* rsp; + char kind[32]; + size_t kind_size = sizeof(kind); status = TeeInitFull(&handle, &MEI_MKHIF, addr, TEE_LOG_LEVEL_VERBOSE, NULL); if (!TEE_IS_SUCCESS(status)) { @@ -73,6 +75,13 @@ int main(int argc, char* argv[]) return 1; } + status = TeeGetKind(&handle, kind, &kind_size); + if (!TEE_IS_SUCCESS(status)) { + fprintf(stderr, "TeeGetKind failed with status = %u\n", status); + } else { + printf("Tee device kind is %s\n", kind); + } + while (retry--) { status = TeeConnect(&handle); if (status != TEE_BUSY && From a3036253a9ccd8054aebb28968e65cd156b77c87 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Wed, 26 Feb 2025 15:07:49 +0200 Subject: [PATCH 04/18] MeTee: EFI: TeeGetKind empty implementation Will be implemented separately Signed-off-by: Abliyev, Reuven --- src/uefi/metee_efi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/uefi/metee_efi.c b/src/uefi/metee_efi.c index d23b0b8..661d780 100644 --- a/src/uefi/metee_efi.c +++ b/src/uefi/metee_efi.c @@ -711,4 +711,9 @@ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) return 0; } return handle->protcolVer; +} + +TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) +{ + return TEE_NOTSUPPORTED; } \ No newline at end of file From 65719e389c38bff81b41bb0fe4c35632c11e67dc Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Wed, 26 Feb 2025 15:08:56 +0200 Subject: [PATCH 05/18] MeTee: linux: TeeGetKind empty implementation Will be implemented separately Signed-off-by: Abliyev, Reuven --- src/linux/metee_linux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/linux/metee_linux.c b/src/linux/metee_linux.c index 6ef4a44..7bb71a6 100644 --- a/src/linux/metee_linux.c +++ b/src/linux/metee_linux.c @@ -594,4 +594,9 @@ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) return 0; } return handle->protcolVer; +} + +TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) +{ + return TEE_NOTSUPPORTED; } \ No newline at end of file From 20e70d68e33eef41079351a275cb13a57cd43ab3 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Sun, 2 Mar 2025 13:58:04 +0200 Subject: [PATCH 06/18] MeTee: tests: TeeGetKind test Implemented for Windows only Signed-off-by: Abliyev, Reuven --- tests/metee_test.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/metee_test.cpp b/tests/metee_test.cpp index 39a2910..3edf43f 100644 --- a/tests/metee_test.cpp +++ b/tests/metee_test.cpp @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ #include #include @@ -467,6 +467,26 @@ TEST_P(MeTeeTEST, PROD_N_TestLongClientPath) ASSERT_EQ(TEE_CLIENT_NOT_FOUND, ConnectRetry(&handle)); } +TEST_P(MeTeeTEST, PROD_N_TestGetMeiKind) +{ + TEEHANDLE handle = TEEHANDLE_ZERO; + struct MeTeeTESTParams intf = GetParam(); + char kind[64]; + size_t kind_size = sizeof(kind); + TEESTATUS status; + + status = TestTeeInitGUID(&handle, &GUID_NON_EXISTS_CLIENT, intf.device); + ASSERT_EQ(TEE_SUCCESS, status); +#ifdef WIN32 + ASSERT_EQ(TEE_SUCCESS, TeeGetKind(&handle, kind, &kind_size)); +#else + ASSERT_EQ(TEE_NOTSUPPORTED, TeeGetKind(&handle, kind, &kind_size)); +#endif + + TeeDisconnect(&handle); + EXPECT_EQ(TEE_INVALID_DEVICE_HANDLE, TeeGetDeviceHandle(&handle)); +} + TEST_P(MeTeeOpenTEST, PROD_N_TestGetDriverVersion) { teeDriverVersion_t ver = {0, 0, 0, 0}; From 79fce3670285d252d746da2880548b0a5c8874f7 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Thu, 6 Mar 2025 13:53:16 +0200 Subject: [PATCH 07/18] MeTee: Linux: pull libmei 1.6.4 New getkind API. Signed-off-by: Abliyev, Reuven --- src/linux/libmei.h | 12 +++++++- src/linux/mei.c | 75 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/linux/libmei.h b/src/linux/libmei.h index 1d2b99c..de9f3a7 100644 --- a/src/linux/libmei.h +++ b/src/linux/libmei.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2013 - 2024 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2025 Intel Corporation. All rights reserved. * * Intel Management Engine Interface (Intel MEI) Library */ @@ -256,6 +256,16 @@ int mei_fwstatus(struct mei *me, uint32_t fwsts_num, uint32_t *fwsts); */ int mei_gettrc(struct mei *me, uint32_t *trc_val); +/*! Obtains device kind + * + * \param me The mei handle + * \param kind buffer to fill with device kind null terminated string, may be NULL. + * \param kind_size Pointer to kind buffer size in bytes, updated to number of bytes filled in buffer, including null character, on out. + * If buffer is NULL, required size is returned anyway. + * \return 0 if successful, otherwise error code + */ +int mei_getkind(struct mei *me, char *kind, size_t *kind_size); + /*! Set log level * * \param me The mei handle diff --git a/src/linux/mei.c b/src/linux/mei.c index 2b81db4..70192af 100644 --- a/src/linux/mei.c +++ b/src/linux/mei.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-3-Clause * - * Copyright(c) 2013 - 2024 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2025 Intel Corporation. All rights reserved. * * Intel Management Engine Interface (Intel MEI) Library */ @@ -337,6 +337,50 @@ static inline int __mei_gettrc(struct mei *me, const char *device, uint32_t *trc #undef CONV_BASE } +static inline int __mei_getkind(struct mei *me, const char *device, char *kind, size_t *kind_size) +{ +#define KIND_FILENAME_LEN 34 +#define KIND_LEN 16 + char path[KIND_FILENAME_LEN]; + char buf[KIND_LEN] = { 0 }; + int fd; + ssize_t len; + + if (snprintf(path, KIND_FILENAME_LEN, + "/sys/class/mei/%s/kind", device) < 0) + return -EINVAL; + path[KIND_FILENAME_LEN - 1] = '\0'; + + errno = 0; + fd = open(path, O_CLOEXEC, O_RDONLY); + if (fd == -1) { + me->last_err = errno; + return -me->last_err; + } + + errno = 0; + len = pread(fd, buf, KIND_LEN, 0); + if (len == -1) { + me->last_err = errno; + close(fd); + return -me->last_err; + } + + close(fd); + if ((size_t)len > *kind_size || !kind) { + me->last_err = ENOSPC; + mei_err(me, "Insufficient buffer %zu %zd\n", *kind_size, len); + *kind_size = (size_t)len; + return -me->last_err; + } + *kind_size = (size_t)len; + memcpy(kind, buf, (size_t)len); + + return 0; +#undef KIND_FILENAME_LEN +#undef KIND_LEN +} + int mei_init_with_log(struct mei *me, const char *device, const uuid_le *guid, unsigned char req_protocol_version, bool verbose, mei_log_callback log_callback) @@ -736,6 +780,35 @@ int mei_gettrc(struct mei *me, uint32_t *trc_val) return 0; } +int mei_getkind(struct mei *me, char *kind, size_t *kind_size) +{ + char *device; + int rc; + + if (!me || !kind_size) + return -EINVAL; + + if (me->device) { + device = strstr(me->device, MEI_DEFAULT_DEVICE_PREFIX); + if (!device) { + mei_err(me, "Device does not start with '%s'\n", + MEI_DEFAULT_DEVICE_PREFIX); + return -EINVAL; + } + device += strlen(MEI_DEFAULT_DEVICE_PREFIX); + } else { + device = MEI_DEFAULT_DEVICE_NAME; + } + rc = __mei_getkind(me, device, kind, kind_size); + if (rc < 0) { + mei_err(me, "Cannot get kind value [%d]:%s\n", + rc, strerror(-rc)); + return rc; + } + + return 0; +} + unsigned int mei_get_api_version(void) { return LIBMEI_API_VERSION; From 0b5de39c00bf208d777f3175409eacec94ea825e Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Thu, 6 Mar 2025 13:54:49 +0200 Subject: [PATCH 08/18] MeTee: Linux: TeeGetKind implementation Implement TeeGetKind on linux via /sys/class/mei/kind driver interface. Signed-off-by: Abliyev, Reuven --- src/linux/metee_linux.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/linux/metee_linux.c b/src/linux/metee_linux.c index 7bb71a6..0af367b 100644 --- a/src/linux/metee_linux.c +++ b/src/linux/metee_linux.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ #include #include @@ -73,6 +73,7 @@ static inline TEESTATUS errno2status(ssize_t err) case -EACCES: return TEE_PERMISSION_DENIED; case -EOPNOTSUPP: return TEE_NOTSUPPORTED; case -ECANCELED: return TEE_UNABLE_TO_COMPLETE_OPERATION; + case -ENOSPC: return TEE_INSUFFICIENT_BUFFER; default : return TEE_INTERNAL_ERROR; } } @@ -598,5 +599,36 @@ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) { - return TEE_NOTSUPPORTED; + struct mei* me = to_mei(handle); + TEESTATUS status; + int rc; + + if (!handle) { + return TEE_INVALID_PARAMETER; + } + + FUNC_ENTRY(handle); + + if (!me || !kindSize) { + status = TEE_INVALID_PARAMETER; + ERRPRINT(handle, "One of the parameters was illegal\n"); + goto End; + } + + rc = mei_getkind(me, kind, kindSize); + if (rc < 0) { + status = errno2status(rc); + if (status == TEE_INSUFFICIENT_BUFFER) { + DBGPRINT(handle, "Insufficient buffer %zu\n", *kindSize); + } else { + ERRPRINT(handle, "kind get failed with status %d %s\n", rc, strerror(-rc)); + } + goto End; + } + + status = TEE_SUCCESS; + +End: + FUNC_EXIT(handle, status); + return status; } \ No newline at end of file From 70ecc6d341332981a49c023e43a342fbe3f13657 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Thu, 6 Mar 2025 13:57:48 +0200 Subject: [PATCH 09/18] MeTee: tests: TeeGetKind test linux Enable test for linux Signed-off-by: Abliyev, Reuven --- tests/metee_test.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/metee_test.cpp b/tests/metee_test.cpp index 3edf43f..b0b51a2 100644 --- a/tests/metee_test.cpp +++ b/tests/metee_test.cpp @@ -477,11 +477,8 @@ TEST_P(MeTeeTEST, PROD_N_TestGetMeiKind) status = TestTeeInitGUID(&handle, &GUID_NON_EXISTS_CLIENT, intf.device); ASSERT_EQ(TEE_SUCCESS, status); -#ifdef WIN32 + ASSERT_EQ(TEE_SUCCESS, TeeGetKind(&handle, kind, &kind_size)); -#else - ASSERT_EQ(TEE_NOTSUPPORTED, TeeGetKind(&handle, kind, &kind_size)); -#endif TeeDisconnect(&handle); EXPECT_EQ(TEE_INVALID_DEVICE_HANDLE, TeeGetDeviceHandle(&handle)); From 133547d93ccc030812877a927344527ee491f8dc Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Tue, 4 Mar 2025 12:37:44 +0200 Subject: [PATCH 10/18] MeTee: EFI: Refactor HECI_DEVICE_KIND Existing "kind" field has misleading name, Introduce breaking change and rename it to hw_type instead, Kind term will be dedicated to new new TeeGetKind API Signed-off-by: Abliyev, Reuven --- include/metee.h | 12 ++++++------ src/uefi/metee_efi.c | 15 ++++++++------- src/uefi/metee_efi.h | 1 + 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/metee.h b/include/metee.h index a345f64..49df6ef 100644 --- a/include/metee.h +++ b/include/metee.h @@ -138,12 +138,12 @@ struct tee_device_address { uint32_t device; /** HECI device Device */ uint32_t function; /** HECI device Function */ } value; - /*! Specify HW layout: HECI, FWSTS registers locations */ - enum { - HECI_DEVICE_KIND_PCH, - HECI_DEVICE_KIND_GFX_GSC, - HECI_DEVICE_KIND_GFX_CSC, - } kind; /** HECI device kind */ + /*! Specifies HW layout: HECI, FWSTS registers locations */ + enum HECI_HW_TYPE { + HECI_HW_TYPE_PCH, + HECI_HW_TYPE_GFX_GSC, + HECI_HW_TYPE_GFX_CSC, + } hw_type; /** HECI device HW type */ } bdf; } data; }; diff --git a/src/uefi/metee_efi.c b/src/uefi/metee_efi.c index 661d780..128525d 100644 --- a/src/uefi/metee_efi.c +++ b/src/uefi/metee_efi.c @@ -99,20 +99,20 @@ SetHwInfo( { TEESTATUS status = TEE_INVALID_PARAMETER; FUNC_ENTRY(Handle->TeeHandle); - switch (device->data.bdf.kind) + switch (device->data.bdf.hw_type) { - case HECI_DEVICE_KIND_PCH: + case HECI_HW_TYPE_PCH: Handle->Hw = HwInfoPch(device->data.bdf.value.segment, device->data.bdf.value.bus, device->data.bdf.value.device, device->data.bdf.value.function); - DBGPRINT(Handle->TeeHandle, "******** HECI_DEVICE_KIND_PCH\n"); + DBGPRINT(Handle->TeeHandle, "******** HECI_HW_TYPE_PCH\n"); break; - case HECI_DEVICE_KIND_GFX_GSC: + case HECI_HW_TYPE_GFX_GSC: Handle->Hw = HwInfoGfxGsc(device->data.bdf.value.segment, device->data.bdf.value.bus, device->data.bdf.value.device, device->data.bdf.value.function); - DBGPRINT(Handle->TeeHandle, "******** HECI_DEVICE_KIND_GFX_GSC\n"); + DBGPRINT(Handle->TeeHandle, "******** HECI_HW_TYPE_GFX_GSC\n"); break; default: - DBGPRINT(Handle->TeeHandle, "******** Unsupported device kind %d\n", device->data.bdf.kind); + DBGPRINT(Handle->TeeHandle, "******** Unsupported device kind %d\n", device->data.bdf.hw_type); status = TEE_INVALID_PARAMETER; goto End; } @@ -152,6 +152,7 @@ TeeInitFullTypeEfiDevice( efi_impl->TeeHandle = handle; efi_impl->ClientGuid = *guid; efi_impl->State = METEE_CLIENT_STATE_NONE; + efi_impl->HwType = device->data.bdf.hw_type; SetHwInfo(device, efi_impl); *impl_handle = efi_impl; @@ -222,7 +223,7 @@ TeeInitFull( struct tee_device_address default_device = device; // CSME HECI by default #define PCI_DEVICE_NUMBER_PCH_HECI1 22 - default_device.data.bdf.kind = HECI_DEVICE_KIND_PCH; + default_device.data.bdf.hw_type = HECI_HW_TYPE_PCH; default_device.data.bdf.value.segment = 0; default_device.data.bdf.value.bus = 0; default_device.data.bdf.value.device = PCI_DEVICE_NUMBER_PCH_HECI1; diff --git a/src/uefi/metee_efi.h b/src/uefi/metee_efi.h index cbf2716..853d223 100644 --- a/src/uefi/metee_efi.h +++ b/src/uefi/metee_efi.h @@ -188,6 +188,7 @@ struct METEE_EFI_IMPL enum METEE_CLIENT_STATE State; /** The client state */ HECI_CLIENT_CONNECTION HeciClientConnection; /** HECI EFI Connection information */ struct HECI_HW Hw; /** HECI HW information */ + enum HECI_HW_TYPE HwType; /** HECI HW type */ }; #define HECI_EFI_PRINT_BDF_STR "[HECI %d:%d:%d:%d] " From ef1312bde99cf7dff6bdc4ac4786dd35cc05ad98 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Mon, 3 Mar 2025 20:21:31 +0200 Subject: [PATCH 11/18] MeTee: EFI: TeeGetKind implementation Implement TeeGetKind on EFI via existing get FW status interface. Signed-off-by: Abliyev, Reuven --- src/uefi/metee_efi.c | 66 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/uefi/metee_efi.c b/src/uefi/metee_efi.c index 128525d..4844e58 100644 --- a/src/uefi/metee_efi.c +++ b/src/uefi/metee_efi.c @@ -714,7 +714,71 @@ uint8_t TEEAPI TeeGetProtocolVer(IN const PTEEHANDLE handle) return handle->protcolVer; } +typedef enum TEEDRIVER_PLATFORM_KIND_ +{ + TEEDRIVER_PLATFORM_KIND_MEI = 0, + TEEDRIVER_PLATFORM_KIND_IOE = 1, + TEEDRIVER_PLATFORM_KIND_GSC = 2, + TEEDRIVER_PLATFORM_KIND_MAX = 3, +} TEEDRIVER_PLATFORM_KIND; + +#define HECI1_IOE_SKU_BIT_START 0 +#define HECI1_IOE_SKU_BIT_NUMS 4 +#define HECI1_IOE_SKU_BIT_MASK (((1 << HECI1_IOE_SKU_BIT_NUMS) - 1) << HECI1_IOE_SKU_BIT_START) +#define HECI1_IOE_SKU 0x1 +#define HECI1_FW_STS3 2 + TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) { - return TEE_NOTSUPPORTED; + UINT8* propertyMap[TEEDRIVER_PLATFORM_KIND_MAX] = { + "mei", + "ioe", + "gscfi", + }; + + TEESTATUS status; + EFI_STATUS efi_status; + UINT32 fw_sts3; + UINT32 kind_ind = 0; + UINTN kind_len; + if (NULL == handle) + { + return TEE_INVALID_PARAMETER; + } + FUNC_ENTRY(handle); + struct METEE_EFI_IMPL *impl_handle = to_int(handle); + + if (NULL == impl_handle || NULL == kindSize) { + status = TEE_INVALID_PARAMETER; + ERRPRINT(handle, "One of the parameters was illegal"); + goto End; + } + + if (impl_handle->HwType == HECI_HW_TYPE_PCH) { + efi_status = HeciFwStatus(impl_handle, HECI1_FW_STS3, &fw_sts3); + if (EFI_ERROR(efi_status)) + { + ERRPRINT(handle, "Failed to retrieve FW Status %d\n", efi_status); + status = TEE_INTERNAL_ERROR; + goto End; + } + kind_ind = ((fw_sts3 & HECI1_IOE_SKU_BIT_MASK) == HECI1_IOE_SKU) ? TEEDRIVER_PLATFORM_KIND_IOE : TEEDRIVER_PLATFORM_KIND_MEI; + } else { + kind_ind = TEEDRIVER_PLATFORM_KIND_GSC; + } + + kind_len = AsciiStrLen(propertyMap[kind_ind]) + 1; + if (kind_len > *kindSize || NULL == kind) { + DBGPRINT(handle, "Insufficient buffer %d %d\n", *kindSize, kind_len); + *kindSize = kind_len; + status = TEE_INSUFFICIENT_BUFFER; + goto End; + } + CopyMem(kind, propertyMap[kind_ind], kind_len); + *kindSize = kind_len; + status = TEE_SUCCESS; + +End: + FUNC_EXIT(handle, status); + return status; } \ No newline at end of file From 8e03f23e9dba70c7aedfc014096257d15200f4ae Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 24 Jun 2020 15:33:41 +0300 Subject: [PATCH 12/18] MeTee: Add cpp wrapper Add c++ class and exception to ease of c++ usage. Signed-off-by: Alexander Usyskin --- conanfile.py | 2 +- include/Doxyfile.in | 2 +- include/meteepp.h | 337 +++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 3 +- tests/metee_test.h | 40 ++++- tests/meteepp_test.cpp | 139 +++++++++++++++++ 6 files changed, 519 insertions(+), 4 deletions(-) create mode 100644 include/meteepp.h create mode 100644 tests/meteepp_test.cpp diff --git a/conanfile.py b/conanfile.py index 48f483d..09cb002 100644 --- a/conanfile.py +++ b/conanfile.py @@ -46,4 +46,4 @@ def package(self): cmake.install() def package_info(self): - self.cpp_info.libs = ["metee"] + self.cpp_info.components["libmetee"].libs = ["metee"] diff --git a/include/Doxyfile.in b/include/Doxyfile.in index 32bd38f..89a8718 100644 --- a/include/Doxyfile.in +++ b/include/Doxyfile.in @@ -936,7 +936,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @DOXYGEN_INPUT_DIRECTORY@/include/metee.h +INPUT = @DOXYGEN_INPUT_DIRECTORY@/include/metee.h @DOXYGEN_INPUT_DIRECTORY@/include/meteepp.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/include/meteepp.h b/include/meteepp.h new file mode 100644 index 0000000..383ce57 --- /dev/null +++ b/include/meteepp.h @@ -0,0 +1,337 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2021-2025 Intel Corporation + */ +/*! \file meteepp.h + \brief metee C++ library API + */ +#ifndef _METEEPP_H_ +#define _METEEPP_H_ + +#include +#include +#include +#include +#include +#include "metee.h" + +namespace intel { + namespace security { + + /*! \def TEE_ERR_STATE(state) + * Internal macro + */ + + /*! MeTee error category class */ + static class metee_category_t : public std::error_category { + public: + virtual const char* name() const noexcept { return "MeTee"; } + virtual std::string message(int ev) const { +#define TEE_ERR_STATE(state) case TEE_##state: return #state + switch (ev) { + TEE_ERR_STATE(SUCCESS); + TEE_ERR_STATE(INTERNAL_ERROR); + TEE_ERR_STATE(DEVICE_NOT_FOUND); + TEE_ERR_STATE(DEVICE_NOT_READY); + TEE_ERR_STATE(INVALID_PARAMETER); + TEE_ERR_STATE(UNABLE_TO_COMPLETE_OPERATION); + TEE_ERR_STATE(TIMEOUT); + TEE_ERR_STATE(NOTSUPPORTED); + TEE_ERR_STATE(CLIENT_NOT_FOUND); + TEE_ERR_STATE(BUSY); + TEE_ERR_STATE(DISCONNECTED); + TEE_ERR_STATE(INSUFFICIENT_BUFFER); + TEE_ERR_STATE(PERMISSION_DENIED); + default: + return std::to_string(ev); + } +#undef TEE_ERR_STATE + } + } metee_category; + + /*! MeTee error exception class class */ + class metee_exception : public std::system_error + { + public: + /*! Constructor + * \param what error string + * \param err error code + */ + metee_exception(const std::string& what, int err = TEE_INTERNAL_ERROR) : std::system_error(err, metee_category, what) {} + /*! Constructor + * \param err error code + * \param cat error category + */ + metee_exception(int err, const std::error_category& cat) : std::system_error(err, cat) {} + /*! Constructor + * \param err error code + * \param cat error category + * \param what error string + */ + metee_exception(int err, const std::error_category& cat, const std::string& what) + : std::system_error(err, cat, what) {} + /*! Destructor */ + virtual ~metee_exception() noexcept {} + }; + + /*! Dummy client GUID for default constructor */ + DEFINE_GUID(METEE_GUID_ZERO, + 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + + /*! Main interface class + * \brief C++ class to access CSE/CSME/GSC firmware via a mei interface. + */ + class metee + { + public: + /*! Default constructor */ + metee() + { + TEESTATUS status = TeeInit(&_handle, &METEE_GUID_ZERO, NULL); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Init failed", status); + } + } + + /*! Constructor + * \param guid GUID of the FW client that want to start a session + * \param log_level log level to set (from enum tee_log_level) + * \param log_callback pointer to function to run for log write, set NULL to use built-in function + */ + metee(const GUID &guid, + uint32_t log_level = TEE_LOG_LEVEL_VERBOSE, TeeLogCallback log_callback = nullptr) + { + struct tee_device_address device = { tee_device_address::TEE_DEVICE_TYPE_NONE , nullptr }; + TEESTATUS status = TeeInitFull(&_handle, &guid, device, log_level, log_callback); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Init failed", status); + } + } + + /*! Constructor + * \param guid GUID of the FW client that want to start a session + * \param device device address structure + * \param log_level log level to set (from enum tee_log_level) + * \param log_callback pointer to function to run for log write, set NULL to use built-in function + */ + metee(const GUID &guid, const struct tee_device_address &device, + uint32_t log_level = TEE_LOG_LEVEL_VERBOSE, TeeLogCallback log_callback = nullptr) + { + TEESTATUS status = TeeInitFull(&_handle, &guid, device, log_level, log_callback); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Init failed", status); + } + } + + /*! Copy constructor - disabled */ + metee(const metee& other) = delete; + + /*! Move constructor + * \param other Object to move from + */ + metee(metee&& other) noexcept : _handle(other._handle) + { + other._handle.handle = nullptr; + } + + /*! Copy operator - disabled */ + metee& operator=(const metee& other) = delete; + + /*! Move operator + * \param other Object to move from + */ + metee& operator=(metee&& other) noexcept + { + TeeDisconnect(&_handle); + _handle = other._handle; + other._handle.handle = nullptr; + return *this; + } + + /*! Destructor, disconnects, if connected */ + virtual ~metee() + { + TeeDisconnect(&_handle); + } + + /*! Connects to the TEE driver and starts a session */ + void connect() + { + TEESTATUS status; + + status = TeeConnect(&_handle); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Connect failed", status); + } + } + + /*! Read data from the TEE device synchronously. + * \param timeout The timeout to complete read in milliseconds, zero for infinite + * \return vector with data read from the TEE device + */ + std::vector read(uint32_t timeout) + { + TEESTATUS status; + size_t size = 0; + std::vector buffer(max_msg_len()); + + status = TeeRead(&_handle, buffer.data(), buffer.size(), &size, timeout); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Read failed", status); + } + + buffer.resize(size); + return std::move(buffer); + } + + /*! Writes the specified buffer to the TEE device synchronously. + * \param buffer vector containing the data to be written to the TEE device. + * \param timeout The timeout to complete write in milliseconds, zero for infinite + * \return the number of bytes written + */ + size_t write(const std::vector &buffer, uint32_t timeout) + { + TEESTATUS status; + size_t size = 0; + + status = TeeWrite(&_handle, buffer.data(), buffer.size(), &size, timeout); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("Write failed", status); + } + + return size; + } + + /*! Retrieves specified FW status register. + * \param fwStatusNum The FW status register number (0-5). + * \return obtained FW status. + */ + uint32_t fw_status(uint32_t fwStatusNum) + { + TEESTATUS status; + uint32_t fwStatus = 0; + + status = TeeFWStatus(&_handle, fwStatusNum, &fwStatus); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("FWStatus failed", status); + } + + return fwStatus; + } + + /*! Retrieves TRC register. + * \return TRC value. + */ + uint32_t trc() + { + TEESTATUS status; + uint32_t trc_val = 0; + + status = TeeGetTRC(&_handle, &trc_val); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("GetTRC failed", status); + } + + return trc_val; + } + + /*! Retrieves device kind. + * \return kind string value. + */ + std::string kind() + { + TEESTATUS status; + const size_t KIND_SIZE = 32; + char kind[KIND_SIZE]; + size_t kind_size = KIND_SIZE; + + status = TeeGetKind(&_handle, kind, &kind_size); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("TeeGetKind failed", status); + } + + return kind; + } + /*! Set log level + * + * \param log_level log level to set + * \return previous log level + */ + uint32_t log_level(uint32_t log_level) + { + return TeeSetLogLevel(&_handle, log_level); + } + + /*! Retrieve current log level + * + * \return current log level + */ + uint32_t log_level() + { + return TeeGetLogLevel(&_handle); + } + + /*! Set log callback + * + * \param log_callback pointer to function to run for log write, set NULL to use built-in function + */ + void log_callback(TeeLogCallback log_callback) + { + TeeSetLogCallback(&_handle, log_callback); + } + + /*! Retrieve client maximum message length (MTU) + * + * \return client maximum message length. + */ + uint32_t max_msg_len() + { + return TeeGetMaxMsgLen(&_handle); + } + + /*! Retrieve client protocol version + * + * \return client protocol version. + */ + uint8_t protocol_ver() + { + return TeeGetProtocolVer(&_handle); + } + + /*! Returns handle of TEE device + * Obtains HECI device handle on Windows and mei device file descriptor on Linux + * \return the handle of the session. + */ + TEE_DEVICE_HANDLE device_handle() + { + return TeeGetDeviceHandle(&_handle); + } + + /*! Obtains version of the TEE device driver + * Not implemented on Linux + * \return Driver version as dotted string. + */ + std::string driver_version() + { + TEESTATUS status; + teeDriverVersion_t driverVersion = { 0 }; + + status = ::GetDriverVersion(&_handle, &driverVersion); + if (!TEE_IS_SUCCESS(status)) { + throw metee_exception("GetDriverVersion failed", status); + } + + std::stringstream ss; + ss << driverVersion.major << "." + << driverVersion.minor << "." + << driverVersion.hotfix << "." + << driverVersion.build; + return ss.str(); + } + + private: + _TEEHANDLE _handle; /*!< Internal device handle */ + }; + } // namespace security +} // namespace intel +#endif // _METEEPP_H_ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 847d926..4344119 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Copyright (C) 2014-2024 Intel Corporation +# Copyright (C) 2014-2025 Intel Corporation cmake_minimum_required(VERSION 3.15) project(metee_test) @@ -46,6 +46,7 @@ add_subdirectory( add_executable(${PROJECT_NAME} Main.cpp metee_test.cpp + meteepp_test.cpp $<$:${CMAKE_SOURCE_DIR}/src/Windows/metee_winhelpers.c> ) if(NOT CONSOLE_OUTPUT) diff --git a/tests/metee_test.h b/tests/metee_test.h index fa8758d..a745418 100644 --- a/tests/metee_test.h +++ b/tests/metee_test.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* - * Copyright (C) 2014-2024 Intel Corporation + * Copyright (C) 2014-2025 Intel Corporation */ #include #include @@ -13,6 +13,7 @@ #include #include "metee.h" +#include "meteepp.h" #include "helpers.h" #ifdef WIN32 #include @@ -93,6 +94,43 @@ class MeTeeTEST : public ::testing::TestWithParam{ GEN_GET_FW_VERSION MkhiRequest; }; +class MeTeePPTEST : public ::testing::TestWithParam { +public: + MeTeePPTEST() { + // initialization code here + } + + void SetUp() { + GEN_GET_FW_VERSION req; +#ifdef _DEBUG + printf("Enter ProdTests SetUp\n"); +#endif + req.Header.Fields.Command = GEN_GET_FW_VERSION_CMD; + req.Header.Fields.GroupId = MKHI_GEN_GROUP_ID; + req.Header.Fields.IsResponse = 0; + auto ptr = reinterpret_cast(&req); + MkhiRequest = std::vector(ptr, ptr + sizeof(GEN_GET_FW_VERSION)); +#ifdef _DEBUG + printf("Exit ProdTests SetUp\n"); +#endif + } + + void TearDown() { +#ifdef _DEBUG + printf("Enter ProdTests TearDown\n"); +#endif + std::this_thread::sleep_for(std::chrono::milliseconds(100)); +#ifdef _DEBUG + printf("Exit ProdTests TearDown\n"); +#endif + } + + ~MeTeePPTEST() { + // cleanup any pending stuff, but no exceptions allowed + } + std::vector MkhiRequest; +}; + class MeTeeFDTEST : public ::testing::TestWithParam { public: MeTeeFDTEST() : deviceHandle(TEE_INVALID_DEVICE_HANDLE) { diff --git a/tests/meteepp_test.cpp b/tests/meteepp_test.cpp new file mode 100644 index 0000000..6cbc30b --- /dev/null +++ b/tests/meteepp_test.cpp @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (C) 2021-2025 Intel Corporation + */ +#include "metee_test.h" + +DEFINE_GUID(GUID_NON_EXISTS_CLIENT, + 0x85eb8fa6, 0xbdd, 0x4d01, 0xbe, 0xc4, 0xa5, 0x97, 0x43, 0x4e, 0xd7, 0x62); + +TEST_P(MeTeePPTEST, PROD_MKHI_SimpleGetVersion) +{ + struct MeTeeTESTParams intf = GetParam(); + std::vector MaxResponse; + GEN_GET_FW_VERSION_ACK* pResponseMessage; + + for (int i = 1; i < 2; i++) { + try { + intel::security::metee metee(*intf.client); + + ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); + metee.connect(); + + ASSERT_EQ(MkhiRequest.size(), metee.write(MkhiRequest, 0)); + + MaxResponse = metee.read(0); + ASSERT_LE(sizeof(GEN_GET_FW_VERSION_ACK), MaxResponse.size()); + pResponseMessage = reinterpret_cast(MaxResponse.data()); + + ASSERT_EQ(TEE_SUCCESS, pResponseMessage->Header.Fields.Result); + EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeMajor); + EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeBuildNo); + } + catch(const intel::security::metee_exception &ex){ + if (ex.code().value() == TEE_DEVICE_NOT_FOUND) + GTEST_SKIP(); + FAIL() << "Excepton: " << ex.what(); + } + } +} + +TEST_P(MeTeePPTEST, PROD_N_Kind) +{ + struct MeTeeTESTParams intf = GetParam(); + + try { + intel::security::metee metee(*intf.client); + + ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); + + ASSERT_GE(metee.kind().length(), 0); + } + catch (const intel::security::metee_exception& ex) { + if (ex.code().value() == TEE_DEVICE_NOT_FOUND) + GTEST_SKIP(); + if (ex.code().value() != TEE_NOTSUPPORTED) + FAIL() << "Excepton: " << ex.what(); + } +} + +TEST_P(MeTeePPTEST, PROD_MKHI_InitFull) +{ + struct MeTeeTESTParams intf = GetParam(); + std::vector MaxResponse; + GEN_GET_FW_VERSION_ACK* pResponseMessage; + + try { + struct tee_device_address device = {tee_device_address::TEE_DEVICE_TYPE_NONE, { NULL }}; + + intel::security::metee metee(*intf.client, device, TEE_LOG_LEVEL_VERBOSE, NULL); + + ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); + metee.connect(); + } + catch (const intel::security::metee_exception& ex) { + if (ex.code().value() == TEE_DEVICE_NOT_FOUND) + GTEST_SKIP(); + FAIL() << "Excepton: " << ex.what(); + } +} + +TEST_P(MeTeePPTEST, PROD_N_TestConnectToNonExistsUuid) +{ + struct MeTeeTESTParams intf = GetParam(); + + try { + intel::security::metee metee(GUID_NON_EXISTS_CLIENT); + ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); + metee.connect(); + } + catch (const intel::security::metee_exception& ex) { + if (ex.code().value() == TEE_DEVICE_NOT_FOUND) + GTEST_SKIP(); + if (ex.code().value() == TEE_CLIENT_NOT_FOUND) + return; + FAIL() << "Excepton: " << ex.what(); + } + FAIL(); +} + +TEST_P(MeTeePPTEST, PROD_MKHI_MoveSemantics) +{ + struct MeTeeTESTParams intf = GetParam(); + std::vector MaxResponse; + GEN_GET_FW_VERSION_ACK* pResponseMessage; + + intel::security::metee metee2; + + try { + intel::security::metee metee(*intf.client); + ASSERT_NE(TEE_INVALID_DEVICE_HANDLE, metee.device_handle()); + metee.connect(); + + metee2 = std::move(metee); + } + catch (const intel::security::metee_exception& ex) { + if (ex.code().value() == TEE_DEVICE_NOT_FOUND) + GTEST_SKIP(); + FAIL() << "Excepton: " << ex.what(); + } + + ASSERT_EQ(MkhiRequest.size(), metee2.write(MkhiRequest, 0)); + + MaxResponse = metee2.read(0); + ASSERT_LE(sizeof(GEN_GET_FW_VERSION_ACK), MaxResponse.size()); + pResponseMessage = reinterpret_cast(MaxResponse.data()); + + ASSERT_EQ(TEE_SUCCESS, pResponseMessage->Header.Fields.Result); + EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeMajor); + EXPECT_NE(0, pResponseMessage->Data.FWVersion.CodeBuildNo); +} + +static struct MeTeeTESTParams interfaces[1] = { + {"PCH", NULL, &GUID_DEVINTERFACE_MKHI}}; + +INSTANTIATE_TEST_SUITE_P(MeTeePPTESTInstance, MeTeePPTEST, + testing::ValuesIn(interfaces), + [](const testing::TestParamInfo& info) { + return info.param.name; + }); \ No newline at end of file From a1bb5f5b25972597ed69ef631aee2445a15f6745 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 9 Mar 2025 09:20:56 +0200 Subject: [PATCH 13/18] MeTee: account for old Windows driver Return NOT_SUPPOPRTED if there is no kind property provided by Windows driver. Signed-off-by: Alexander Usyskin --- src/Windows/metee_winhelpers.c | 5 +++++ tests/metee_test.cpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Windows/metee_winhelpers.c b/src/Windows/metee_winhelpers.c index 854cd9b..ad4c478 100644 --- a/src/Windows/metee_winhelpers.c +++ b/src/Windows/metee_winhelpers.c @@ -309,6 +309,11 @@ TEESTATUS GetDeviceKind(IN PTEEHANDLE handle, IN OUT OPTIONAL char *kind, IN OUT prop_size = 0; cr = CM_Get_DevNode_PropertyW(devInstHandle, &DEVPKEY_TeedriverKindString, &prop_type, NULL, &prop_size, 0); + if (cr == CR_NO_SUCH_VALUE) { + DBGPRINT(handle, "CM_Get_DevNode_Property: kind not found\n"); + status = TEE_NOTSUPPORTED; + goto Cleanup; + } if (cr != CR_BUFFER_SMALL) { ERRPRINT(handle, "CM_Get_DevNode_Property: %d %d\n", cr, prop_size); status = TEE_INTERNAL_ERROR; diff --git a/tests/metee_test.cpp b/tests/metee_test.cpp index b0b51a2..e401fdb 100644 --- a/tests/metee_test.cpp +++ b/tests/metee_test.cpp @@ -478,7 +478,8 @@ TEST_P(MeTeeTEST, PROD_N_TestGetMeiKind) status = TestTeeInitGUID(&handle, &GUID_NON_EXISTS_CLIENT, intf.device); ASSERT_EQ(TEE_SUCCESS, status); - ASSERT_EQ(TEE_SUCCESS, TeeGetKind(&handle, kind, &kind_size)); + status = TeeGetKind(&handle, kind, &kind_size); + ASSERT_TRUE(status == TEE_SUCCESS || status == TEE_NOTSUPPORTED); TeeDisconnect(&handle); EXPECT_EQ(TEE_INVALID_DEVICE_HANDLE, TeeGetDeviceHandle(&handle)); From e2fd3c7dd4d8444e30008040443e2dfb385e3c32 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 5 Mar 2025 15:48:09 +0200 Subject: [PATCH 14/18] MeTee: CMake: Windows: add release 64 static preset Add release 64bit Static preset. Signed-off-by: Alexander Usyskin --- CMakePresets.json | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 52d0a1a..7239d7c 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -33,7 +33,7 @@ }, { "name": "Debug32AllStatic", - "displayName": "Windows x86 Debug All", + "displayName": "Windows x86 Debug Static All", "description": "Build x86 Debug, VS2019, including test and samples", "inherits": "base32", "binaryDir": "${sourceDir}/Debug", @@ -46,7 +46,7 @@ }, { "name": "Release32AllStatic", - "displayName": "Windows x86 Release All", + "displayName": "Windows x86 Release Static All", "description": "Build x86 Release, VS2019, including test and samples", "inherits": "base32", "binaryDir": "${sourceDir}/Release", @@ -59,7 +59,7 @@ }, { "name": "Release32Static", - "displayName": "Windows x86 Release", + "displayName": "Windows x86 Release Static", "description": "Build x86 Release, VS2019", "inherits": "base32", "binaryDir": "${sourceDir}/Release", @@ -88,6 +88,17 @@ "CMAKE_BUILD_TYPE": "Release" } }, + { + "name": "Release64Static", + "displayName": "Windows x86-64 Release Static", + "description": "Build x86-64 Release, VS2019", + "inherits": "base64", + "binaryDir": "${sourceDir}/Release", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "BUILD_SHARED_LIBS": "NO" + } + }, { "name": "Debug64All", "displayName": "Windows x86-64 Debug All", @@ -127,6 +138,11 @@ "configurePreset": "Release64", "configuration": "Release" }, + { + "name": "Release64Static", + "configurePreset": "Release64Static", + "configuration": "Release" + }, { "name": "Debug64All", "configurePreset": "Debug64All", From 82708c4af6e87e642227cbe13bf760ea5d98866d Mon Sep 17 00:00:00 2001 From: "Briskman, Yitzhak" Date: Thu, 6 Mar 2025 16:58:34 +0200 Subject: [PATCH 15/18] MeTee: UEFI: Fixing compilation errors with GCC Fixing 2 GCC warnings: - using VA_ARGS without ## - instance of variable inside switch/case Signed-off-by: Briskman, Yitzhak --- src/uefi/metee_efi.c | 3 ++- src/uefi/metee_efi.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/uefi/metee_efi.c b/src/uefi/metee_efi.c index 4844e58..8bfe45d 100644 --- a/src/uefi/metee_efi.c +++ b/src/uefi/metee_efi.c @@ -182,6 +182,7 @@ TeeInitFull( IN OPTIONAL TeeLogCallback log_callback) { TEESTATUS status = TEE_INTERNAL_ERROR; + struct tee_device_address default_device = device; if (NULL == guid) { @@ -220,7 +221,7 @@ TeeInitFull( status = TEE_INVALID_PARAMETER; goto Cleanup; } - struct tee_device_address default_device = device; + // CSME HECI by default #define PCI_DEVICE_NUMBER_PCH_HECI1 22 default_device.data.bdf.hw_type = HECI_HW_TYPE_PCH; diff --git a/src/uefi/metee_efi.h b/src/uefi/metee_efi.h index 853d223..2f3d90c 100644 --- a/src/uefi/metee_efi.h +++ b/src/uefi/metee_efi.h @@ -194,6 +194,6 @@ struct METEE_EFI_IMPL #define HECI_EFI_PRINT_BDF_STR "[HECI %d:%d:%d:%d] " #define HECI_EFI_PRINT_BDF_VAL Handle->Hw.Bdf.Segment, Handle->Hw.Bdf.Bus, Handle->Hw.Bdf.Device, Handle->Hw.Bdf.Function -#define EFIPRINT(Handle, fmt, ...) DBGPRINT(Handle, HECI_EFI_PRINT_BDF_STR fmt, HECI_EFI_PRINT_BDF_VAL, __VA_ARGS__); +#define EFIPRINT(Handle, fmt, ...) DBGPRINT(Handle, HECI_EFI_PRINT_BDF_STR fmt, HECI_EFI_PRINT_BDF_VAL, ##__VA_ARGS__); #endif // METEE_EFI_H_ From 66775b5fb9d3d0bc52ea1cfd662a69c4db6b0255 Mon Sep 17 00:00:00 2001 From: "Abliyev, Reuven" Date: Mon, 10 Mar 2025 14:17:44 +0200 Subject: [PATCH 16/18] MeTee: EFI: Decrease HW register polling timeout Experiments show that current value is too big and affects performance Decreasing value will provide reasonable performance level Signed-off-by: Abliyev, Reuven --- src/uefi/heci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uefi/heci_core.c b/src/uefi/heci_core.c index 89dfdc9..37394c7 100644 --- a/src/uefi/heci_core.c +++ b/src/uefi/heci_core.c @@ -99,7 +99,7 @@ GetFilledSlots( #define DelayExecutionFlow gBS->Stall -#define TIMER_STEP 20000 +#define TIMER_STEP 1000 /** Checks if FW is ready for communication over the HECI interface. From 2abeef1204e82367f73154f923684a8e05c8c017 Mon Sep 17 00:00:00 2001 From: "Adin, Menachem" Date: Tue, 11 Mar 2025 10:57:00 +0200 Subject: [PATCH 17/18] MeTee: EFI: Change propertyMap array type to CHAR8* Fix build with gcc - signed/unsigned conversion. Signed-off-by: Menachem Adin --- src/uefi/metee_efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uefi/metee_efi.c b/src/uefi/metee_efi.c index 8bfe45d..ed1cc0b 100644 --- a/src/uefi/metee_efi.c +++ b/src/uefi/metee_efi.c @@ -731,7 +731,7 @@ typedef enum TEEDRIVER_PLATFORM_KIND_ TEESTATUS TEEAPI TeeGetKind(IN PTEEHANDLE handle, IN OUT char *kind, IN OUT size_t *kindSize) { - UINT8* propertyMap[TEEDRIVER_PLATFORM_KIND_MAX] = { + CHAR8* propertyMap[TEEDRIVER_PLATFORM_KIND_MAX] = { "mei", "ioe", "gscfi", From 9dcf64f4fbf2e0041822bad2c7379392bc2aa144 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 19 Mar 2025 11:16:53 +0200 Subject: [PATCH 18/18] MeTee: bump version to 5.0.0 Update CHANGELOG.md Signed-off-by: Alexander Usyskin --- CHANGELOG.md | 22 ++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b7370c..aa10479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## [5.0.0] + +**Note:** Backward incompatible API change: + The HECI_DEVICE_KIND_* enums and kind field in struct tee_device_address + are renamed to HECI_HW_TYPE_* and hw_type field to avoid clash with + device kind value provided by OS drivers. + +### Changed + - EFI: Decrease HW register polling timeout + - EFI: Refactor HECI_DEVICE_KIND + - Linux: pull libmei 1.6.4 + +### Fixed + - EFI: Change propertyMap array type to CHAR8* + - EFI: Fixing compilation errors with GCC + - account for old Windows driver + +### Added + - CMake: Windows: add release 64 static preset + - Add cpp wrapper + - TeeGetKind API + ## [4.3.1] ### Fixed diff --git a/VERSION b/VERSION index f77856a..0062ac9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.3.1 +5.0.0