2025-11-28 00:35:46 +09:00

126 lines
4.0 KiB
C++

//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
/*++
This app demonstrates the life cycle of a VBS enclave including
making function calls into the enclave.
--*/
#include "precomp.h"
HRESULT Run()
{
if (!IsEnclaveTypeSupported(ENCLAVE_TYPE_VBS))
{
printf("VBS Enclave not supported\n");
return E_NOTIMPL;
}
// Create the enclave
constexpr ENCLAVE_CREATE_INFO_VBS CreateInfo
{
ENCLAVE_VBS_FLAG_DEBUG, // Flags
{ 0x10, 0x20, 0x30, 0x40, 0x41, 0x31, 0x21, 0x11 }, // OwnerID
};
PVOID Enclave = CreateEnclave(GetCurrentProcess(),
nullptr, // Preferred base address
0x10000000, // size
0,
ENCLAVE_TYPE_VBS,
&CreateInfo,
sizeof(ENCLAVE_CREATE_INFO_VBS),
nullptr);
RETURN_LAST_ERROR_IF_NULL(Enclave);
// Ensure we terminate and delete the enclave even if something goes wrong.
auto cleanup = wil::scope_exit([&]
{
// fWait = TRUE means that we wait for all threads in the enclave to terminate.
// This is necessary because you cannot delete an enclave if it still has
// running threads.
LOG_IF_WIN32_BOOL_FALSE(TerminateEnclave(Enclave, TRUE));
// Delete the enclave.
LOG_IF_WIN32_BOOL_FALSE(DeleteEnclave(Enclave));
});
// Load enclave module with SEM_FAILCRITICALERRORS enabled to suppress
// the error message dialog.
{
DWORD previousMode = GetThreadErrorMode();
SetThreadErrorMode(previousMode | SEM_FAILCRITICALERRORS, nullptr);
auto restoreErrorMode = wil::scope_exit([&]
{
SetThreadErrorMode(previousMode, nullptr);
});
RETURN_IF_WIN32_BOOL_FALSE(LoadEnclaveImageW(Enclave, L"vbsenclave.dll"));
}
// Initialize the enclave with one thread.
// Once initialized, no more DLLs can be loaded into the enclave.
ENCLAVE_INIT_INFO_VBS InitInfo{};
InitInfo.Length = sizeof(ENCLAVE_INIT_INFO_VBS);
InitInfo.ThreadCount = 1;
RETURN_IF_WIN32_BOOL_FALSE(InitializeEnclave(GetCurrentProcess(),
Enclave,
&InitInfo,
InitInfo.Length,
nullptr));
// Locate the function in the enclave.
PENCLAVE_ROUTINE Routine = reinterpret_cast<PENCLAVE_ROUTINE>(GetProcAddress(reinterpret_cast<HMODULE>(Enclave), "CallEnclaveTest"));
RETURN_LAST_ERROR_IF_NULL(Routine);
// Call the function. Our test function XOR's its input with a magic number.
ULONG_PTR Input = 0x1234;
void* Output;
RETURN_IF_WIN32_BOOL_FALSE(CallEnclave(Routine, reinterpret_cast<void*>(Input), TRUE /* fWaitForThread */, &Output));
// Verify that it performed the expected calculation.
if ((reinterpret_cast<ULONG_PTR>(Output) ^ Input) != 0xDADAF00D)
{
printf("Unexpected result from enclave\n");
}
// Destructor of "cleanup" variable will terminate and delete the enclave.
return S_OK;
}
int
main(
[[maybe_unused]] _In_ int argc,
[[maybe_unused]] _In_reads_(argc) char** argv
)
{
// Print diagnostic messages to the console for developer convenience.
wil::SetResultLoggingCallback([](wil::FailureInfo const& failure) noexcept
{
wchar_t message[1024];
wil::GetFailureLogString(message, ARRAYSIZE(message), failure);
wprintf(L"Diagnostic message: %ls\n", message);
});
HRESULT hr = Run();
if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_IMAGE_HASH))
{
wprintf(L"If you developer-signed the DLL, make sure that you have enabled test signing.\n");
}
return SUCCEEDED(hr) ? EXIT_SUCCESS : EXIT_FAILURE;
}