Properly Detecting Intel® Software Guard Extensions (Intel® SGX) in Your Applications

Overview

Intel® Software Guard Extensions (Intel® SGX) SDK provides three functions for detecting and enabling Intel SGX support on systems. The CPUID instruction also provides an interface for detecting Intel SGX support on a CPU. The key question for software developers: what is the proper way to detect Intel SGX support on a system so that my applications and their installers behave accordingly?

This seems like a simple question. If the processor supports Intel SGX, the application can safely bring up enclaves and use them for protecting secrets from other software that is running on the system. If the processor does not support Intel SGX, the developer can choose to cease function on the application (and present an error to the user), or fall back to a non-Intel SGX code path.

That sounds easy, but the reality is far more complicated. To understand why, it’s necessary to understand the details behind Intel SGX support in a CPU, how that’s managed, and how it’s reported to applications.

Intel® Software Guard Extensions (Intel® SGX) Support on a Platform

While an individual CPU may support Intel SGX, whether or not Intel SGX is actually available for use depends on two components:

  • BIOS
  • Intel SGX Platform Software package

We discuss both of these in detail below.

BIOS Support

BIOS support is required for Intel SGX to provide the capability to enable and configure the Intel SGX feature in the system.

The system owner must opt in to Intel SGX by enabling it via the BIOS. This requires a BIOS from the OEM that explicitly supports Intel SGX. The support provided by the BIOS can vary OEM to OEM and even across an OEM’s product lines.

There are three possible BIOS settings.

  • Enabled
    Intel Software Guard Extensions (Intel® SGX) is enabled and available for use in applications.

  • Software Controlled
    Intel SGX can be enabled by software applications, but it is not available until this occurs (called the “software opt-in”). Enabling Intel SGX via software opt-in may require a system reboot.

  • Disabled
    Intel SGX is explicitly disabled and it cannot be enabled through software applications. This setting can only be changed in the BIOS setup screen.

Note: Your BIOS may only have the Enabled and Disabled options, or it may not have these options if it only supports the Software Controlled option (or if it doesn’t support Intel SGX at all). Check with your device manufacturer to determine whether or not Intel SGX is supported on your system.

When Intel SGX is set to Enabled in the BIOS, Intel SGX has been enabled, and Intel SGX instructions and resources are available to applications.

When Intel SGX is set to Software Controlled, Intel SGX is initially disabled until it is enabled via a software application that makes one of the following calls in the SDK:

  • sgx_enable_device()
  • sgx_cap_enable_device()

These functions perform the software opt-in and are described in more detail below. Intel’s recommendation to OEMs and ODMs is to provide the Software Controlled mode and make this the default setting.

When Intel SGX is set to Disabled, it is explicitly disabled and cannot be enabled via software. To enable Intel SGX, the end user must either:

Set it back to the Enabled state in the BIOS.

Or:

Set it to the Software Controlled state in the BIOS (at which point, Intel SGX is still disabled until it is enabled via a software application).

What is the point of the Software Controlled state?

Intel SGX reserves up to 128 MB of system RAM as Processor Reserved Memory (PRM), which is used to hold the Enclave Page Cache (EPC). While its exact size is determined by the BIOS settings, it is important to note that enabling Intel SGX consumes a portion of the system’s resources, effectively making them unavailable to other applications.

The Software Controlled setting in the BIOS allows OEMs to ship systems with support for Intel SGX in a ready state, where it can be activated via software (this is the software opt-in). This is a compromise between having Intel SGX fully enabled by default and potentially consuming system resources even when no Intel SGX software is present on the system and having it turned off completely. Allowing the activation to occur via software eliminates the need for end users to boot their systems into their BIOS setup screens and manually enable Intel SGX via that interface, a potentially daunting task for nontechnical users.

Software enabling is a one-way operation: Intel SGX cannot be disabled via software. The only ways to disable Intel SGX once it has been enabled are to do so via the BIOS:

Explicitly set Intel SGX to Disabled if the BIOS provides this option.

Or:

Flash a new BIOS image to the device, which resets Intel SGX support in the BIOS to the default state (either Disabled or Software Controlled, depending on the BIOS provider).

The Platform Software Package

For Intel SGX to function, the Intel SGX Platform Software package, or PSW, must be installed on the system. The PSW includes:

  • Runtime libraries
  • Services that support and maintain the trusted compute block on the end user’s system
  • Services that perform and manage critical Intel SGX operations such as attestation
  • Interfaces to platform services such as the trusted time and monotonic counters

The PSW is installed by the software vendor as part of the application installation procedure. It is up to the software vendor’s application installer to detect whether or not the platform supports Intel SGX, and, if so, run the PSW installer.

If the Platform Software is already installed on the system, the PSW installation package will either upgrade the existing installation (if the existing installation is older) or exit without taking further action.

Windows* platforms

These two libraries are installed into the system directory on Windows platforms:

  • sgx_uae_service.dll
  • sgx_urts.dll

An application needs to load the DLLs in this order.

Linux* platforms

These two libraries are installed into the system library directory on Linux platforms (typically /usr/lib or /usr/lib64):

  • libsgx_uae_service.so
  • libsgx_urts.so

Applications need to load the shared objects in this order.

Use dynamic loading, not dynamic linking

Applications with both Intel SGX and non-Intel SGX code paths in a single binary must dynamically load the Intel SGX runtime libraries. Dynamic linking is not an option, since systems that lack Intel SGX support will not have the PSW package installed. Attempting to run a dynamically linked executable on a system without the PSW package will result in unresolved symbol errors that prevent the application from launching.

Note that the check for the PSW package that is described above begins with a dynamic load of the necessary shared libraries. The application can simply keep these handles open.

Windows developers using Microsoft Visual Studio* can enable the Delayed-Loaded DLL support in the linker via the /DELAYLOAD option. When enabled, Visual Studio automatically generates a helper function that performs dynamic loading for the target DLLs as needed at runtime. This allows the developer to write their software as if they were dynamically linking the libraries while actually implementing dynamic loading.

Linux developers will need to explicitly use dynamic loading in their applications.

PSW library security

As a general rule, application should load the PSW libraries from the system directories where they are installed.

Windows systems can call GetSystemDirectory() to obtain the system directory path, and SetDllDirectory() to set the DLL search path to that directory, prior to calling LoadLibrary().

Properly configured Linux systems should specify the system library paths in /etc/ld.so.conf, but ultimately the user has significant control over the runtime environment through the LD_LIBRARY_PATH environment variable.

However, regardless of the platform the application is running on, the OS is outside of the Trusted Compute Base and malicious software can attempt to influence the preferred load order of dynamic libraries. This can lead to a denial of service of Intel SGX. Application developers can take basic precautions to mitigate against dynamic library preload attacks, but there are no foolproof solutions.

What about CPUID?

The CPUID instruction is not sufficient to detect the usability of Intel SGX on a platform. It can report whether or not the processor supports the Intel SGX instructions, but Intel SGX usability depends on both the BIOS settings and the PSW. Applications that make decisions based solely on CPUID enumeration run the risk of generating a #GP or #UD fault at runtime.

In addition, VMMs (for example, Hyper-V*) can mask CPUID results, and thus a system may support Intel SGX even though the results of the CPUID report that the Intel SGX feature flag is not set.

The Intel® Software Guard Extensions Feature-Detection Procedure for Windows Systems

When developing an application, Intel SGX detection must occur both within the application at runtime and the application installer. Each has its own procedure.


Figure 1: Intel® Software Guard Extensions feature-detection flowchart for installers.

Windows Application Installers

All Intel SGX applications must install the PSW. It does not make sense to install the PSW on a system that cannot support Intel SGX. Application installers must check the local system for Intel SGX capability before attempting to install the PSW and must also complete the software opt-in to enable Intel SGX. The recommended procedure is shown in Figure 1.

  1. Call sgx_is_capable(). If the system is Intel SGX-capable, go to step 2. If not, do not install the PSW and do not attempt the software opt-in. It is up to the application vendor to decide what to do next, but in general the options are:
    • Install the application if it supports both Intel SGX and non-Intel SGX code paths.
    • Install the non-Intel SGX version of the application if it’s distributed as a separate binary.
    • Abort the installation entirely if Intel SGX support is required and tell the user that the software is incompatible with the machine configuration.
  2. Run the PSW installer. If the installation succeeds, go to step 3. Otherwise, abort the installation.
  3. Call sgx_cap_enable_device() to enable Intel SGX, and then check the return result.
    • If the result is that Intel SGX is enabled, no further action is needed.
    • If enabling Intel SGX is successful but a reboot is required, prompt the user that a reboot is necessary to run the newly installed application.
    • If enabling Intel SGX is unsuccessful, present an error to the user.

Note that the two functions sgx_is_capable() and sgx_cap_enabled_device() both require administrator privileges. Application installers generally require this level of permission, so it would not be unusual for the Intel SGX application installer to trigger a UAC prompt in Windows.

Because the installer containing these functions may run before the PSW has been installed, they are provided in standalone DLLs that are intended to be bundled with the installer program.

Windows Applications

Detecting Intel SGX in an application at runtime is different from detecting it in an application installer. Once the application has been installed, one of the following scenarios is possible:

  1. The system was not detected as Intel SGX-capable by the installer and thus does not have the Intel SGX PSW.
  2. The system was detected as being Intel SGX-capable by the installer and thus does have the Intel SGX Platform Software installed on it. The state of Intel SGX is either:
    • Enabled, either via explicitly being enabled in the BIOS or via the software opt-in via the installer.
    • Enabled pending the software opt-in, meaning the user needs to reboot their system before Intel SGX instructions can be executed.
    • Disabled, meaning the user has explicitly disabled Intel SGX at some point after the application was installed.

Regardless of which case applies, the correct procedure for applications to follow is shown in Figure 2.

image of a flowchart
Figure 2: Intel® Software Guard Extensions feature-detection flowchart for Microsoft Windows* applications.

  1. Check to see whether the PSW has been installed. If it has, go to step 2. If not, Intel SGX is not available on the platform, and the action it should take is dependent on the code paths in the application itself.
    • If the application supports a non-Intel SGX code branch, it should execute the non-Intel SGX code.
    • If the application is Intel SGX-only, it must exit.
  2. Call sgx_enable_device() to ensure that the software opt-in has occurred, and check the return value.
    • If the result is that Intel SGX is enabled, the application may execute the Intel SGX code path.
    • If Intel SGX could not be enabled, the application should fall back to the non-Intel SGX code path (if it has one), or exit (if it doesn’t).
    • If the result is that a reboot or some other manual action is required, such as a BIOS change, the application should inform the user of what action needs to be taken. The application can continue with a non-Intel SGX code path if desired.

The Intel® Software Guard Extensions Feature-Detection Procedure for Linux Systems

The procedures for Linux systems are similar to those for Windows systems, but are complicated by disparities between the two platforms.

  • The AESM service on Windows, which is part of the PSW, has always provided support for the software enable operation from user-level processes. As of this writing, the Linux distribution of the PSW does not provide this capability.
  • The Windows distribution of the SDK includes a DLL named sgx_capable.dll, which contains functions for detecting Intel SGX capability as well as performing the software enable when running with administrator privileges. This library is intended to be used by application installers. The 1.9 and earlier versions of the Intel SDK for Linux do not include an equivalent library. However it is available in a branch of the source code repository as both a static and dynamic library (libsgx_capable.a and libsgx_capable.so, respectively). It is expected to be merged into the main distribution in a future release.

Linux Application Installers

The procedure for application installers on Linux is identical to that on Windows and must call into libsgx_capable to perform the feature detection and software enable functions. Application installers can choose to either statically or dynamically link against this library.

Note that sgx_cap_enable_device() requires root privileges in order to perform the software enable, so applications installers need to be run as root.

Linux Applications

The procedure for applications assumes that the Linux distribution of the PSW will eventually reach parity with Windows and, specifically, include the sgx_enable_device() function. If this function is not found, applications should fall back to the sgx_cap_get_status() function from libsgx_capable. Applications should statically link against this library.

Note that unlike Windows, user-mode processes can detect the state of Intel SGX thanks to the efivarfs filesystem.

The procedure to follow for Linux applications is shown in Figure 3.

image of a flwochart
Figure 3: Intel® Software Guard Extensions feature-detection flowchart for Linux* applications.

  1. Check to see whether the PSW has been installed. If so, go to step 2. If not, Intel SGX is not available on the platform, and the action it should take depends on the code paths in the application itself.
    • If the application supports a non-Intel SGX code branch, it should execute the non-Intel SGX code.
    • If the application is Intel SGX-only, it must exit.
  2. Determine whether the function sgx_enable_device() is defined in libsgx_uae_service.so.
    • If sgx_enable_device() is defined, call that function to attempt the software enable and get the resulting status of Intel SGX.
    • If this function is not found, call sgx_cap_get_status() to get the current status of Intel SGX.
  3. Check the status of Intel SGX obtained from step 2.
    • If the result is that Intel SGX is enabled, the application may execute the Intel SGX code path.
    • If Intel SGX could not be enabled, the application should fall back to the non-Intel SGX code path (if it has one), or exit (if it doesn’t).
    • If the result is that a reboot or some other manual action is required, such as a BIOS change, the application should inform the user of what action needs to be taken. The application can continue with a non-Intel SGX code path if desired.

Nuances

Disabled versus No Support

It is not possible to differentiate between the following three cases:

  • Intel SGX is not supported by the CPU
  • Intel SGX is not supported by the BIOS
  • Intel SGX is supported by the BIOS and CPU, but explicitly disabled in the BIOS

The procedure for the installer should not change, however. In all three cases, sgx_is_capable() will return a zero, which indicates that the platform is not Intel SGX-capable.

Linking libsgx_capable on Linux

The Intel SGX SDK for Linux builds both a static and dynamic version of libsgx_capable. Application installers can choose either static or dynamic linking, but the applications themselves should statically link this library when possible for the following reasons:

  • Use of libsgx_capable in Linux applications is a bridge solution for runtime feature detection, intended to be used only until the PSW on Linux supports the software enable capability and, specifically, the sgx_enable_device() function.
  • The sgx_capable.dll library is not part of the Intel SGX runtime on Windows and is not distributed as part of the PSW package. In order to minimize inconsistencies between the two platforms, Linux systems should not install either libsgx_capable.so or libsgx_capable.a onto end-user devices.
  • The runtime feature detection procedure for Linux applications is structured to automatically deprecate the use of the functions present in libsgx_capable. Dynamic linking would result in an unused library on the end-user’s system.

Intel® Software Guard Extensions SDK Feature-Detection Functions

The enabling procedures make use of four functions from the Intel SGX SDK:

  • sgx_is_capable()
  • sgx_cap_enable_device()
  • sgx_cap_get_status()
  • sgx_enable_device()

These functions are described below. For more information, read the function reference in the Intel SGX SDK.

sgx_is_capable

sgx_status_t sgx_is_capable(int *sgx_capable)

This function determines whether the system is capable of executing Intel SGX instructions under the current operating environment. The return value is type sgx_status_t and indicates success or failure of the inquiry.

Return values

If it returns SGX_SUCCESS, the system was successfully queried for Intel SGX support and the result is stored in *sgx_capable. A return of SGX_ERROR_NO_PRIVILEGE means the installer was not run with administrator privileges.

Any other return value means that the Intel SGX capability of the system could not be determined. In this case, application installers should be conservative and assume that the system is not Intel SGX capable.

Output parameters

A return value of SGX_SUCCESS does not mean that the system is capable of supporting Intel SGX, only that it was able to definitively answer the question. To determine whether the system is Intel SGX-capable, you must examine the value of *sgx_capable: a value of 1 means “yes,” and a value of 0 means “no.”

Notes

This function reports only a yes or a no, with no other information. It is intended to be a quick filter used by application installers. If the function reports that the system is Intel SGX-capable, the installer should proceed with installing the PSW package. The PSW is required to be bundled with all Intel SGX-capable application installers. If the system is not SGX-capable, the installer should not attempt to install the PSW package.

Windows

On Windows systems, this function requires administrative privileges in order to access the EFI variables.

Application installers need to include the DLL sgx_capable.dll in their installation package.

Linux

On Linux systems, the OS must have been installed and booted in UEFI mode and the efi filesystem must be mounted so that the function can access the EFI variables. If the efi filesystem is not available or can’t be accessed, it will fail to detect systems in the Software Control state as being Intel SGX-capable.

Application installers need to include the libsgx_capable.so shared library with their installer package or statically link the installer against libsgx_capable.a.

sgx_cap_enable_device

sgx_status_t sgx_cap_enable_device (sgx_device_status_t *sgx_device_status)

This function attempts the software opt-in for Intel SGX and sets the final state of SGX in *sgx_device_status. The return value is type sgx_status_t and indicates whether the system can attempt the software opt-in. The return value does not indicate whether the Intel SGX device itself was successfully enabled. That information is stored in *sgx_device_status only if the software opt-in was attempted.

This function requires administrator privileges because it must access the Software Control Interface made available via the BIOS. It is intended to be called by application installers, and executed after the PSW has been installed in order to enable Intel SGX.

Return values

If this function returns SGX_SUCCESS, the software opt-in was attempted, and the success or failure of that attempt is stored in *sgx_device_status.

If the return value is SGX_ERROR_NO_PRIVILEGE, the installer was not run with administrator privileges.

Any other return value means that the software opt-in could not be attempted on this system or in the current environment. In this case, application installers should be conservative and assume that Intel SGX cannot be enabled via the software opt-in on this system.

Output parameters

A return value of SGX_SUCCESS does not mean that Intel SGX was successfully enabled, merely that the software opt-in was attempted. The value stored in *sgx_device_status must be checked next.

SGX_ENABLED means that Intel SGX was already enabled.

SGX_DISABLED_REBOOT_REQUIRED means that the software opt-in was successful, but a reboot is required for completion of Intel SGX enabling. Applications that attempt to detect Intel SGX usability at runtime will be told that Intel SGX is not available until the reboot occurs.

Any other value indicates that the software opt-in failed, and the user must manually enable Intel SGX via the BIOS setup screen.

Notes

Because this function requires administrative privileges, it should not be run by Intel SGX applications. However, it is currently the only method for performing the software enable on Linux systems, so it would be appropriate to use in a standalone binary intended to be executed by root for that purpose.

Windows

Windows application installers need to include the DLL sgx_capable.dll in their installation package.

Linux

Linux applications installers need to include the libsgx_capable.so shared library with their installer package or statically link the installer against libsgx_capable.a.

sgx_cap_get_status

sgx_status_t sgx_cap_get_status (sgx_device_status_t *sgx_device_status)

This function checks the status of Intel SGX on the current system, and if it’s not available the status code indicates the reason why. It is an alternative to sgx_is_capable() when more information about the status of Intel SGX is desired.

On Windows, this is intended to be used only by application installers. On Linux, it may be used by both applications and installers.

Windows

On Windows systems, this function requires administrative privileges in order to access the EFI variables.

It is intended to be used by application installers, so that the user can be asked to confirm enabling Intel SGX via the software control interface. If the function reports the *sgx_device_status code SGX_DISABLED_SCI_AVAILABLE, the installer will proceed with the software enable procedure.

Installers need to include the DLL sgx_capable.dll in their installation package.

Linux

On Linux systems, the OS must have been installed and booted in UEFI mode and the efi filesystem must be mounted so that the function can access the EFI variables. If the efi filesystem is not available or can’t be accessed then it will fail to detect systems in the Software Control state as being Intel SGX-capable.

When used in an application installer, if the function reports that the system is Intel SGX-capable the installer should proceed installing the PSW package. The PSW is required to be bundled with all Intel SGX-capable application installers. If the system is not Intel SGX-capable, the installer should not attempt to install the PSW package.

Linux installers will need to include the libsgx_capable.so shared library with their installer package or statically link the installer against libsgx_capable.a.

sgx_enable_device

sgx_status_t sgx_enable_device (sgx_device_status_t *sgx_device_status)

This function is similar to sgx_cap_enable_device(), but it is intended to be run by applications instead of installers.

It does not require administrative privileges; it contacts the AE Service running on the local machine and asks that service to attempt the software opt-in. Note that this creates a dependency on the PSW: it must be installed on the system.

Applications run sgx_enable_device() to ensure that Intel SGX is available for use, once they have verified that the PSW libraries are present on the system. The return values, and the Intel SGX device status, are nearly identical to sgx_cap_enable_device().

Because the PSW must be installed for this function to work, it must not be called by installers.

Linux

The Linux version of the PSW does not implement this capability, and as a result this function is not included in the Linux version of the Intel SGX SDK.

Obtaining libsgx_capable for Linux

Linux distributions of the Intel SGX SDK versions 1.9 and earlier do not include libsgx_capable. To obtain this library, you must fetch the Intel SGX SDK source from the repository on Github* and build the SDK from the master branch.

The SDK installer will place the libraries in the SDK library directory.

Code Samples

A code sample is provided that implements these procedures as a pair of standalone executables for demonstration purposes: one for application installers and one for applications at runtime. These code samples build in both Windows and Linux.

The function that is responsible for the check in each, is_sgx_supported(), is prototyped as follows:

int is_sgx_supported(UINT*sgx_support);

It returns 1 if it could successfully determine the state of Intel SGX support on the system and 0 if it could not because of an error.

The state of Intel SGX support is placed in the variable sgx_support, which is passed as a pointer to the function. It’s a combination of the following bits:

#define ST_SGX_UNSUPPORTED 0x0
#define ST_SGX_CAPABLE 0x1
#define ST_SGX_ENABLED 0x2
#define ST_SGX_REBOOT_REQUIRED 0x4 
#define ST_SGX_BIOS_ENABLE_REQUIRED 0x8 

A system is able to execute Intel SGX instructions if and only if the ST_SGX_ENABLED bit is set. The other bits simply convey additional information about the state of Intel SGX support, if any, and what further action might be needed to enable it.

Conclusion

Answering the question, at runtime, of whether or not a system has been enabled for Intel SGX is complicated. The dependencies on the BIOS, the PSW, and the end user’s own actions means that Intel SGX can be supported by a system, but not fully enabled or ready for use. Applications need to properly identify the state of Intel SGX support in order to ensure they execute the correct code path, and avoid both false positives and false negatives. The procedures described here are the recommended methods of doing so.

For more complete information about compiler optimizations, see our Optimization Notice.
AttachmentSize
Package icon SGX Feature Detection.zip55.83 KB

6 comments

Top

The revised document with content for Linux has been approved for publication and should be posted in the next few days.

I want to give a quick update on the Linux content. Preliminary code for detecting Intel SGX and performing the software enable is currently available as a pull request to the Intel SGX source repository. It's not officially part of the Intel SGX SDK aat the moment, but it is in review. In the mean time, the branch has been made available publicly via a fork of the source tree for developers to test and experiment with. This code produces most of the functions in the "libsgx_capable" library that is part of the Windows SDK but not present in the Linux version.

Not a hard date, but it should be in a few weeks. Part of the delay had been a lack of parity between the two SDK's: the Linux SDK does not contain the functions for performing feature detection.

Chris M.'s picture

Is there a real ETA for the Linux support content?

The code sample has been updated for the Intel SGX SDK version 1.7.

Add a Comment

Have a technical question? Visit our forums. Have site or software product issues? Contact support.