Compartir a través de


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:

  1. Escribir un archivo DLL de enclave de SBV y una aplicación host correspondiente
  2. Compilar el archivo DLL y el host
  3. Firmar el archivo DLL del enclave de SBV
  4. 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:

Diagrama que ilustra el orden en el que se llama a las API de enclaves de SBV

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:

  1. Empiece por incluir winenclave.h. En el código de ejemplo, consulte Samples/VbsEnclave/Test enclave/precomp.h:

    #include <winenclave.h>
    

    winenclave.h es el archivo de inclusión central para enclaves de SBV e incluye windows.h, ntenclv.h y winenclaveapi.h.

  2. 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, consulte Samples/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.

  3. La función DllMain() es obligatoria y define el punto de entrada al enclave. Se llama durante InitializeEnclave(). En el código de ejemplo, consulte Samples/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;
    }
    
  4. 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, consulte Samples/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:

  1. 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.

  2. [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.

  3. [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.

  4. 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.

  5. 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.

  6. 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 en AdditionalDependencies. 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:

    1. libcmt.lib y libvcruntime.lib: se encuentra en la carpeta enclave con las herramientas de compilación de Visual C++; consulte los ficheros .lib de C runtime (CRT) y biblioteca estándar de C++ (STL).
    2. vertdll.lib y bcrypt.lib: se encuentra en la carpeta um con las bibliotecas de Windows SDK.
    3. ucrt.lib: se encuentra en la carpeta ucrt_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:

  1. EKU de firma de código: 1.3.6.1.5.5.7.3.3

  2. EKU de enclave: 1.3.6.1.4.1.311.76.57.1.15

  3. EKU de autor: el EKU tiene el formato 1.3.6.1.4.1.311.97.X.Y.Z, donde X es mayor que 999.

    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:

  1. 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.
  2. 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:

  1. Adjunte el depurador en modo de usuario al proceso de host del enclave.
  2. Vuelva a cargar los símbolos del enclave después de que el proceso de host haya cargado la imagen del enclave en memoria.
  3. 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.

Introducción a los enclaves de SBV

Firma de confianza de Azure

Encabezado enclaveapi.h

API disponibles en enclaves de SBV