Guía de desarrollo de enclaves de seguridad basada en virtualización (SBV)
Se aplica a:✅ Windows 11 Build 26100.2314 o posterior Windows Server 2025 o posterior ✅
En esta guía de desarrollo se describe cómo compilar, firmar y depurar un enclave básico de SBV.
Requisitos previos
Para comenzar a trabajar con enclaves de SBV, debe cumplir los siguientes requisitos:
- Ver y cumplir los requisitos del dispositivo que se indican en la Información general sobre enclaves de SBV.
- Ver y cumplir los requisitos previos de desarrollo que se indican en la Información general sobre enclaves de SBV.
- Se recomienda instalar la carga de trabajo de Desarrollo de escritorio con C++ a través del instalador de Visual Studio. Instalará todas las herramientas necesarias, incluido el Kit de desarrollo de software de Windows (SDK).
- Descargue el código de ejemplo de GitHub. Muestra el ciclo de vida de un enclave de SBV, incluidas las instrucciones para hacer llamadas de función en el enclave.
- Cada enclave debe tener una aplicación de host. El código de ejemplo contiene una solución de Visual Studio con dos proyectos: el host del enclave y el enclave de prueba.
Introducción
Una vez que cumpla los requisitos previos anteriores, debería poder abrir el archivo de la solución desde la muestra de VbsEnclave en Visual Studio y compilarlo. Creará una aplicación de prueba junto con el enclave correspondiente. Sin embargo, no podrá ejecutar correctamente la aplicación hasta que el enclave esté firmado con un certificado válido.
En esta guía se detalla cómo compilar un enclave básico de SBV en la máquina de desarrollo. Los pasos para compilar un enclave de SBV son:
- Escribir un archivo DLL de enclave de SBV y una aplicación host correspondiente
- Compilar el archivo DLL y el host
- Firmar el archivo DLL del enclave de SBV
- Depuración del enclave de SBV
Comencemos por comprender el ciclo de vida de un enclave. Las API del enclave se llaman en el orden siguiente:
Paso 1: Escritura de los enclaves de SBV
Vamos a examinar el código de ejemplo y comprender cómo escribir una aplicación que emplee un enclave de SBV.
Escritura del host del enclave
Recuerde que el archivo DLL de enclave de SBV es simplemente un archivo DLL y, por tanto, requiere una aplicación de host. La aplicación host no es más que una aplicación windows estándar. Para emplear enclaves de SBV, el host debe usar las API de enclave de Windows del encabezado enclaveapi.h. Al incluir windows.h
en la aplicación host se proporcionará acceso a estas API.
Escritura del archivo DLL que se carga en un enclave de prueba
Consulte el código de ejemplo del proyecto Enclave de prueba para seguir los pasos que se indican a continuación.
En el enclave de muestra, creamos un enclave básico que aplica XOR a la entrada con 0xDADAF00D
y devuelve el resultado. Vamos a desglosar cómo lo hacemos:
Empiece por incluir
winenclave.h
. En el código de ejemplo, consulteSamples/VbsEnclave/Test enclave/precomp.h
:#include <winenclave.h>
winenclave.h
es el archivo de inclusión central para enclaves de SBV e incluyewindows.h
,ntenclv.h
ywinenclaveapi.h
.Cada archivo DLL cargado en un enclave requiere una configuración. Esta configuración se define mediante una variable
const
global denominada__enclave_config
de tipo IMAGE_ENCLAVE_CONFIG. En el código de ejemplo, consulteSamples/VbsEnclave/Test enclave/enclave.c
:const IMAGE_ENCLAVE_CONFIG __enclave_config = { sizeof(IMAGE_ENCLAVE_CONFIG), IMAGE_ENCLAVE_MINIMUM_CONFIG_SIZE, IMAGE_ENCLAVE_POLICY_DEBUGGABLE, // DO NOT SHIP DEBUGGABLE ENCLAVES TO PRODUCTION 0, 0, 0, { 0xFE, 0xFE }, // family id { 0x01, 0x01 }, // image id 0, // version 0, // SVN 0x10000000, // size 16, // number of threads IMAGE_ENCLAVE_FLAG_PRIMARY_IMAGE };
Nota:
Solo puede haber una imagen principal por enclave. Si carga varias imágenes principales, la que se haya cargado primero se tratará como principal y el resto se tratarán como dependencias. En este ejemplo, no hay ninguna otra dependencia aparte de los archivos DLL de la plataforma de enclave.
La función
DllMain()
es obligatoria y define el punto de entrada al enclave. Se llama duranteInitializeEnclave()
. En el código de ejemplo, consulteSamples/VbsEnclave/Test enclave/enclave.c
.BOOL DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD dwReason, _In_ LPVOID lpvReserved ) { UNREFERENCED_PARAMETER(hinstDLL); UNREFERENCED_PARAMETER(lpvReserved); if (dwReason == DLL_PROCESS_ATTACH) { InitialCookie = 0xDADAF00D; } return TRUE; }
Las funciones del enclave que se llaman desde la aplicación host deben exportarse y ser de tipo LPENCLAVE_ROUTINE. La signatura de función tiene este aspecto:
void* CALLBACK enclaveFunctionName(_In_ void* Context)
En el código de ejemplo, consulte
Samples/VbsEnclave/Test enclave/enclave.c
.void* CALLBACK CallEnclaveTest( _In_ void* Context ) { WCHAR String[32]; swprintf_s(String, ARRAYSIZE(String), L"%s\n", L"CallEnclaveTest started"); OutputDebugStringW(String); return (void*)((ULONG_PTR)(Context) ^ InitialCookie); }
Nota:
Solo se puede acceder a las funciones exportadas por la imagen principal del enclave desde la aplicación host.
A continuación, puede exportar la función mediante un archivo
.DEF
. En el código de ejemplo, consulteSamples/VbsEnclave/Test enclave/vbsenclave.def
. Para obtener más información, consulte Exportación desde un archivo DLL mediante archivos DEF.
Y así es como se escribe un archivo DLL de enclave de SBV básico.
Paso 2: Compilación de enclaves de SBV
Ahora que hemos escrito nuestro archivo DLL de enclave de SBV, vamos a compilarlo.
Compilación del host del enclave
La compilación de la aplicación host es igual que la de cualquier aplicación Windows, pero con la adición de onecore.lib
a la lista de dependencias durante la vinculación.
Compilación del archivo DLL del enclave de prueba
Para poder compilar el archivo DLL del enclave de prueba, es necesario hacer algunos cambios en las configuraciones del compilador y del enlazador:
El enlazador de MSVC proporciona una marca
/ENCLAVE
que selecciona los detalles de configuración del enclave. La marca/ENCLAVE
es incompatible con la vinculación incremental, por lo que es necesario establecer/INCREMENTAL:NO
.[Solo configuración de depuración]
/EDITANDCONTINUE
es incompatible con/INCREMENTAL:NO
, por lo que usamos/Zi
en lugar de/ZI
para Formato de depuración de la información en el compilador.[Solo configuración de depuración] La configuración Comprobaciones en tiempo de ejecución básicas debe establecerse en Predeterminado. Las comprobaciones de errores en tiempo de ejecución no se admiten en enclaves de SBV.
La firma digital de un archivo DLL de enclave debe comprobarse en el momento de la carga y requiere configurar la marca
/INTEGRITYCHECK
en el enlazador.Los archivos DLL del enclave se deben instrumentar para la Protección de flujo de control (CFG), y para ello usamos la marca
/GUARD:MIXED
en el enlazador.Los enclaves tienen sus propias versiones de plataforma, inicio, tiempo de ejecución y bibliotecas de UCRT. Para garantizar que no se vinculan versiones que no sean de enclaves, use la marca
/NODEFAULTLIB
. Posteriormente, añada las bibliotecas correctas enAdditionalDependencies
. En el código de ejemplo, estas bibliotecas se encapsulan en la macro VBS_Enclave_Dependencies. A continuación se muestran las bibliotecas de enclaves de SBV:libcmt.lib
ylibvcruntime.lib
: se encuentra en la carpetaenclave
con las herramientas de compilación de Visual C++; consulte los ficheros .lib de C runtime (CRT) y biblioteca estándar de C++ (STL).vertdll.lib
ybcrypt.lib
: se encuentra en la carpetaum
con las bibliotecas de Windows SDK.ucrt.lib
: se encuentra en la carpetaucrt_enclave
con las bibliotecas de Windows SDK.
Nota:
No se admite ninguna otra biblioteca de plataformas en enclaves de SBV.
En resumen, se requieren los siguientes cambios:
Compilador (solo configuración de depuración):
- Formato de información de depuración:
/Zi
- Comprobaciones en tiempo de ejecución básicas:
Default
Enlazador:
/ENCLAVE
/NODEFAULTLIBS
+AdditionalDependencies
/INCREMENTAL:NO
/INTEGRITYCHECK
/GUARD:MIXED
Ya puede compilar el archivo DLL del enclave.
Protección con VEIID
VEIID (la utilidad de enlace de id. de importación de enclave de SBV) es una herramienta de Windows SDK que actualiza las tablas de importación en un enclave de SBV con identificadores conocidos para archivos DLL de plataforma. Esto mejora la seguridad de los enclaves de SBv al evitar que se cargue un archivo DLL (firmado) malintencionado con el mismo nombre que uno de los archivos DLL de la plataforma.
En el código de ejemplo, esto se efectúa automáticamente en un evento posterior a la compilación.
Nota:
Se recomienda encarecidamente que evite utilizar sus propios archivos DLL no primarios, aparte de los archivos DLL de la plataforma. En su lugar, mantenga todo el código dentro del propio archivo DLL del enclave.
Paso 3: Firma de archivos DLL de enclave de SBV
Los enclaves de SBV deben estar firmados para que se carguen correctamente. La firma del enclave contiene información sobre su autor. Se usa para obtener el id. del autor del enclave. Puede firmar como prueba el enclave antes de firmarlo para producción.
Firmar como prueba: local
Cada certificado de firma de enclave requiere al menos tres EKU:
EKU de firma de código:
1.3.6.1.5.5.7.3.3
EKU de enclave:
1.3.6.1.4.1.311.76.57.1.15
EKU de autor: el EKU tiene el formato
1.3.6.1.4.1.311.97.X.Y.Z
, dondeX
es mayor que999
.Para las pruebas, puede optar por usar cualquier EKU de autor que coincida con este patrón. Para producción, se proporcionará un EKU de autor como parte del certificado de producción (a continuación encontrará más detalles sobre la firma de producción).
Ejemplo:
1.3.6.1.4.1.311.97.814040577.346743379.4783502.105532346
Si desea firmar el archivo DLL del enclave mientras lo desarrolla, habilite la firma como prueba. Con la firma como prueba habilitada, puede crear un certificado que contenga estos tres EKU y firmar el enclave con ell. Use el cmdlet New-SelfSignedCertificate para crear un certificado. Tenga en cuenta que los archivos DLL de enclave deben estar firmados con hash de página.
Nota:
Cuando tenga un certificado, puede automatizar el proceso de firma en el evento posterior a la compilación.
New-SelfSignedCertificate -CertStoreLocation Cert:\\CurrentUser\\My -DnsName "MyTestEnclaveCert" -KeyUsage DigitalSignature -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256 -TextExtension "2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.76.57.1.15,1.3.6.1.4.1.311.97.814040577.346743379.4783502.105532346"
signtool sign /ph /fd SHA256 /n "MyTestEnclaveCert" vbsenclave.dll
Con el archivo DLL del enclave firmado, ahora puede cargarlo en un entorno que tenga habilitada la firma como prueba.
Firma de producción: firma de confianza (anteriormente Firma de código de Azure)
La firma de producción para enclaves se proporciona a través del perfil de certificado de enclave de SBV en Firma de confianza. Para obtener más información sobre cómo usar la Firma de confianza, consulte la documentación.
La firma de confianza también le permite firmar el enclave en la línea de comandos. Esto genera un enclave firmado y listo para ejecutarse al compilar el enclave en Visual Studio.
Paso 4: Depuración de enclaves de SBV
Normalmente, la memoria de un enclave está oculta para los depuradores y está protegida desde VTL0. Sin embargo, si quiere depurar el archivo DLL de enclave de SBV, puede compilarlo para que se depure durante el desarrollo. Los enclaves son un proceso en modo de usuario VTL1 y, por tanto, se pueden depurar con un depurador en modo de usuario.
Para poder depurar el enclave:
- La configuración de la imagen del archivo DLL del enclave debe permitir la depuración: esto se hace estableciendo la marca IMAGE_ENCLAVE_POLICY_DEBUGGABLE en IMAGE_ENCLAVE_CONFIG.
- Es necesario permitir la depuración durante la creación del enclave: para ello, se establece la marca ENCLAVE_VBS_FLAG_DEBUG en la estructura ENCLAVE_CREATE_VBS_INFO que se pasa a la llamada CreateEnclave.
Para depurar el enclave:
- Adjunte el depurador en modo de usuario al proceso de host del enclave.
- Vuelva a cargar los símbolos del enclave después de que el proceso de host haya cargado la imagen del enclave en memoria.
- Establezca puntos de interrupción en las funciones del enclave. El depurador las interrumpe mediante una llamada al enclave.
También puede interrumpir en los puntos de interrupción en modo de usuario de CreateEnclave, InitializeEnclave, etc., que depuran paso a paso el código correspondiente en ntdll.dll
.
Nota:
Nunca use enclaves depurables en entornos de producción.
Con esto, ya puede compilar e implementar su primer enclave de SBV. Si tiene alguna pregunta, póngase en contacto con el soporte técnico para desarrolladores de Windows.