Intel Developer Zone Articleshttps://software.intel.com/en-us/articles/43865
Article FeedenIntel® Software Guard Extensions Tutorial Series: Part 10, Enclave Analysis and Debugginghttps://software.intel.com/en-us/articles/intel-software-guard-extensions-tutorial-series-part-10-enclave-analysis-and-debugging
<h2>Introduction</h2>
<p>In part 10 of the <a href="https://software.intel.com/en-us/sgx">Intel® Software Guard Extensions (Intel® SGX)</a> tutorial series we’ll examine two utilities in the Intel SGX Software Development Kit (SDK): the Intel SGX Debugger, and the Enclave Memory Measurement Tool (EMMT). First, we’ll learn how to use the Intel SGX Debugger to inspect enclaves in mixed-mode applications such as our Tutorial Password Manager. Then, we’ll use the EMMT to analyze the memory usage of our enclave in order to optimize its configuration. In the process of doing that, we’ll also find and fix a program bug that has been in the code since Part 3 of the series!</p>
<p>You can find a list of all the published tutorials in the article <a href="/en-us/articles/introducing-the-intel-software-guard-extensions-tutorial-series" rel="nofollow">Introducing the Intel® Software Guard Extensions Tutorial Series</a>. Source code is provided with this installment of the series.</p>
<h2>The Intel® SGX Debugger</h2>
<p>Intel SGX enclaves are intended to keep secrets from being exposed to unauthorized users and programs. Even code running in Ring 0 cannot bypass an enclave’s protections because the security perimeter is enforced by the CPU, regardless of the execution environment. These protections ensure that no untrusted code—whether that be another user, a superuser, the BIOS, or even a virtual machine manager—can inspect enclave memory. Attempts to map enclave memory outside the enclave will yield only the encrypted memory pages. The inability to inspect production enclaves is a key component of the Intel SGX security model.</p>
<p>Software developers, however, frequently use a debugger to analyze a program’s execution in order to find and fix runtime errors in their code, and a debugger can’t function if it doesn’t have access to an application’s memory space. This creates a conflict between security and usability for Intel SGX: The security of enclaves must be preserved, but software developers need the ability to run a debugger when building and testing applications.</p>
<p>Intel’s solution to this problem is twofold:</p>
<ul><li>Only the Intel SGX Debugger can debug enclaves.</li>
<li>Only debug-mode enclaves can be debugged.</li>
</ul><p>The Intel SGX Debugger is required to debug enclaves because Intel SGX defines a specific interface for debugging: It requires the execution of special Intel SGX supervisor instructions. Debuggers without Intel SGX support will not be able to inspect enclaves. The CPU enforces the requirement that only debug-mode enclaves can be inspected with a debugger. This allows developers to create debuggable enclaves in their development environment, and non-debuggable enclaves for distribution.</p>
<p>An enclave’s state as a debug-mode or release-mode enclave is set at build time, and this state is included in the enclave’s metadata. The enclave and its metadata are cryptographically signed using the developer’s signing key. This prevents malicious users from turning a release-mode enclave into a debug-mode enclave: Attempts to manipulate the enclave’s state will change its signature, and the CPU will not launch an enclave if the runtime signature does not match the one that was generated at build time. As an additional protection, debug-mode and release-mode enclaves derive different encryption keys for the Intel SGX sealing functions. A debug-mode enclave cannot access, and thus expose, secrets that were sealed by a release-mode enclave.</p>
<h2>Running the Intel SGX Debugger on Mixed-Mode Applications</h2>
<p>When building a native application on Windows*, using the Intel SGX Debugger is as easy as changing the debugger from the Local Windows Debugger to the Intel SGX Debugger, as shown in Figure 1, and setting the working directory to the same location as the enclave object files (in typical solutions, setting the working path to $(OutDir) will suffice, as shown in Figure 2).</p>
<p style="text-align:center"><img alt="" src="/sites/default/files/managed/ea/22/selecting-intel-sgx-debugg.png" /><br /><strong>Figure 1. </strong><em>Selecting the Intel® SGX Debugger in Microsoft Visual Studio*.</em></p>
<p style="text-align:center"><img alt="" src="/sites/default/files/managed/9c/39/setting-the-working-directory.png" /><br /><strong>Figure 2. </strong><em>Setting the working directory for the Intel® SGX Debugger.</em></p>
<p>When running managed applications, however, you are not given a choice of which debugger to run, and the Intel SGX Debugger can’t debug managed code, anyway. That means you cannot use the <em>Start Debugging</em> feature in Microsoft Visual Studio* to directly debug enclaves that are part of a mixed-mode application. Instead, you need to use the <em>Attach to Process</em> command in the <em>Debug</em> menu. The procedure is as follows:</p>
<ol><li>In Visual Studio, go to the <strong>Debug</strong> menu and select <strong>Attach to Process…</strong></li>
<li>In the <em>Attach to Process</em> dialog box, where it says <em>Attach to…</em> click the <strong>Select…</strong> button. See Figure 3<em>.</em> This will bring up the <em>Select Code Type</em> dialog box.
<p style="text-align:center"><img alt="Attach to process" src="/sites/default/files/managed/0d/ef/attach-to-process-window.png" /><br /><strong>Figure 3. </strong><em>The Attach to Process window.</em></p>
</li>
<li>In the Select Code Type dialog box, click <strong>Debug these code types</strong> and choose <strong>Intel® SGX</strong>, then click <strong>OK.</strong>
<p style="text-align:center"><img alt="" src="/sites/default/files/managed/ff/14/select-code-type.png" /><br /><strong>Figure 4. </strong><em>Selecting the code type to debug.</em></p>
</li>
<li>Execute the application from the output directory via the Windows shell or Windows File Explorer. (<em>Do</em> <em>not</em> run it from within Visual Studio, as this will launch it under the Windows debugger.)</li>
<li>Return to Visual Studio. In the <em>Attach to Process</em> dialog, hit <strong>Refresh</strong> to update the process list, then select the application, and click <strong>Attach</strong>.
<p style="text-align:center"><img alt="Selecting the process to debug" src="/sites/default/files/managed/8c/ae/select-process-to-debug.png" /><br /><strong>Figure 5. </strong><em>Selecting the process to debug.</em></p>
</li>
</ol><p>Note that the Intel SGX Debugger can only inspect native code, whether it’s inside or outside the enclave. You cannot use it to debug managed code.</p>
<h2>The Enclave Memory Measurement Tool</h2>
<p>All enclaves are instantiated in a region of memory known as the enclave page cache, or EPC. The EPC is a shared resource, which means that all running enclaves on the system must fit inside of it. On Windows, the size of the EPC is fixed in the BIOS and cannot be changed (on Linux* systems, the EPC supports paging, which allows the operating system to expand it as needed, but this has performance implications and should be avoided). Because of this restriction, it is extremely important that enclaves be sized to their actual memory usage, and not be allocated more memory than they will use.</p>
<p>The amount of memory allocated to an enclave is set in the enclave’s configuration file; it defaults to 256 KB of stack space per thread and 1 MB of global heap space. The developer can change these values either by editing the .xml file directly, or via the user interface in Visual Studio. Though these values are entered in bytes, <em>they must be 4 KB aligned, since EPC pages are made up of 4 KB chunks</em>.</p>
<p style="text-align:center"><img alt="The enclave settings " src="/sites/default/files/managed/5a/ae/inclave-settings.png" /><br /><strong>Figure 6. </strong><em>The enclave settings for the Tutorial Password Manager.</em></p>
<p>The purpose of the EMMT is to give Windows developers the ability to measure the <em>real</em> memory use of their enclaves so that they can adjust the <em>allocated</em> values accordingly.</p>
<h3>Running the EMMT</h3>
<p>The EMMT application is part of the Intel SGX SDK. Execution is straightforward:</p>
<p><code>sgx_emmt [ –-enclave=<em>enclaves</em> ] <em>program</em> [ arguments ... ]</code></p>
<p>The --enclaves parameter is optional: If your application has multiple enclaves, you can list one or more of them that you want to target; otherwise, the EMMT measures every enclave in your application.</p>
<p>After the application exits, the EMMT prints a memory usage summary for each measured enclave. Figure 7 shows results for an enclave that used 2 KB of stack space and 4 KB from the heap during execution.</p>
<p><code>Enclave: "Enclave.signed.dll"<br />
[Peak stack use]: 0x2KB<br />
[Peak heap use]: 0x4KB </code></p>
<p><strong>Figure 7. </strong><em>Output from the Enclave Memory Measurement Tool.</em></p>
<p>There are two important caveats that must be kept in mind when using the EMMT:</p>
<ul><li>The results show the <em>actual</em> memory used during <em>that specific execution</em> of the application and its enclave. These values may not be typical for the enclave, or even a worst-case usage. It is important that the test run where the measurements are made be as representative of real-world usage as possible, and cover all possible functions. It may be necessary to write a dedicated front-end whose sole job is to stress-test the enclave by exercising its API.</li>
<li>The EMMT does not work on mixed-mode applications. If the main application is written in .NET*, you will not be able to use the EMMT directly on the final application. You will need to write a native front-end application to stress-test the enclave per the above.</li>
</ul><h3>Measuring the Tutorial Password Manager</h3>
<p>The Tutorial Password Manager is a mixed-mode application: The front-end is written in C#, and it connects to the enclave via C++/CLI. Since the EMMT can’t be run on mixed-mode applications, we need to write a native application to call the enclave interface functions in order to measure the memory usage.</p>
<p>To do this, we’ll embed our reference password vault in the application directly as byte arrays (the disk input/output routines in the Tutorial Password Manager are in the C++ .NET layer, so they aren’t available to us to use) and call the wrapper functions in the EnclaveBridge DLL. For demonstration purposes, we’ll perform the following tasks:</p>
<ul><li>Unlock the vault</li>
<li>Get account info for each account</li>
<li>Get the password for each account</li>
<li>Add an account</li>
<li>Change all the account passwords, randomly generating a new password each time</li>
<li>Change the master password</li>
</ul><p>The main program is shown in Figure 8.</p>
<pre class="brush:cpp;">int main()
{
int rv;
uint32_t count;
rv = ew_initialize();
if (rv != 0) {
fprintf(stderr, "ew_initialize: 0x%08x\n", rv);
Exit(1);
}
rv = ew_initialize_from_header(header, header_size);
if (rv != 0) {
fprintf(stderr, "ew_initialize_from_header: 0x%08x\n", rv);
Exit(1);
}
rv = ew_unlock(mpass);
if (rv != 0) {
fprintf(stderr, "ew_unlock: 0x%08x\n", rv);
Exit(1);
}
rv = ew_load_vault(vault_data);
if (rv != 0) {
fprintf(stderr, "ew_load_vault: 0x%08x\n", rv);
Exit(1);
}
rv = ew_accounts_get_count(&amp;count);
if (rv != 0) {
fprintf(stderr, "ew_accounts_get_count: 0x%08x\n", rv);
Exit(1);
}
for (uint32_t i = 0; i &lt; count; ++i) {
uint16_t sname, slogin, surl, spass;
char *name, *login, *url, *pass;
printf("Account %u:\n", i);
rv = ew_accounts_get_info_sizes(i, &amp;sname, &amp;slogin, &amp;surl);
if (rv != 0) {
fprintf(stderr, "ew_accounts_get_info_sizes[%u]: 0x%08x\n", i, rv);
continue;
}
name = new char[sname+1];
login = new char[slogin+1];
url = new char[surl+1];
rv = ew_accounts_get_info(i, name, sname, login, slogin, url, surl);
if (rv != 0) {
fprintf(stderr, "ew_accounts_get_info[%u]: 0x%08x\n", i, rv);
continue;
}
name[sname] = 0;
login[slogin] = 0;
url[surl] = 0;
printf("\tname= %s\n", name);
printf("\tlogin= %s\n", login);
printf("\turl= %s\n", url);
rv = ew_accounts_get_password_size(i, &amp;spass);
if (rv != 0) {
fprintf(stderr, "ew_accounts_get_password_size[%u]: 0x%08x\n", i, rv);
continue;
}
pass = new char[spass + 1];
rv = ew_accounts_get_password(i, pass, spass);
if (rv != 0) {
fprintf(stderr, "ew_accounts_get_password[%u]: 0x%08x\n", i, rv);
continue;
}
pass[spass] = 0;
printf("\tpass= %s\n", pass);
delete[] name;
delete[] login;
delete[] url;
delete[] pass;
}
// Start changing things
// Add an account
rv = ew_accounts_set_info(3, "Acme", 4, "wileye", 6, "http://acme.nodomain/", 21);
if (rv != 0) {
fprintf(stderr, "ew_accounts_set_info[3]: 0x%08x\n", rv);
Exit(1);
}
// Change the passwords many times
for (int i = 0; i &lt; 4; ++i) {
uint32_t idx = i % 4;
char newpass[32];
int rv;
rv = ew_accounts_generate_password(31, 0xffff, newpass);
if (rv != 0) {
fprintf(stderr, "ew_accounts_generate_password[%d]: 0x%08x\n", i, rv);
Exit(1);
}
rv = ew_accounts_set_password(idx, newpass, 31);
if (rv != 0) {
fprintf(stderr, "ew_accounts_set_password[%d]: 0x%08x\n", i, rv);
Exit(1);
}
}
// Change the master password
rv = ew_change_master_password(mpass, new_mpass);
if (rv != 0) {
fprintf(stderr, "ew_change_master_password: 0x%08x\n", rv);
Exit(1);
}
Exit(0);
}
</pre>
<p><strong>Figure 8. </strong> <em>Program listing for the native test application.</em></p>
<p>Initially, we’ll change each account password once, just to get some output and see where our memory usage stands.</p>
<p>After building and executing the test application under the EMMT, we get the following:</p>
<p><code>&gt; sgx_emmt "CLI Native Test App.exe"<br />
The command line is: "cli native Test App.exe ".<br />
Enclave: "Enclave.signed.dll"<br />
[Peak stack use]: 0x2KB<br />
[Peak heap use]: 0x4KB </code><br /><strong>Figure 9. </strong> <em>EMMT output for the Tutorial Password Manager's enclave.</em></p>
<p>Because the size of the password vault is fixed, we don’t expect the Tutorial Password Manager to use a lot of enclave memory, and according to the EMMT it doesn’t. However, changing passwords just <em>once</em> isn’t much of a stress test, and the encryption and decryption functions may need more memory than is shown in this simple test. So, we’ll modify the test program to change each password 1000 times and see how that affects our results.</p>
<p>After recompiling and executing, we get the output shown in Figure 10:</p>
<p><code>The command line is: "cli native Test App.exe ".<br />
Enclave: "Enclave.signed.dll"<br />
[Peak stack use]: 0x2KB<br />
[Peak heap use]: 0xc0KB</code><br /><strong>Figure 10.</strong> <em>EMMT output after increasing the number of password changes.</em></p>
<p>This result, however, is unexpected. Originally, we used only 4 KB of stack space, but it has jumped to 192 KB. If there was a small increase that would possibly make sense, but a <em>48x</em> increase does not! Increasing the number of password changes to 5000 causes yet another increase in the heap usage:</p>
<p><code>[Peak heap use]: 0x3acKB</code><br /><strong>Figure 11. </strong> <em>EMMT output after further increasing the number of password changes.</em></p>
<p>This suggests we have a memory leak in the enclave.</p>
<p>The loop responsible for changing the password is invoking these two ECALLs:</p>
<ul><li><code>ve_accounts_generate_password()</code></li>
<li><code>ve_accounts_set_password()</code></li>
</ul><p>A quick review of E_Vault.cpp turns up the culprit. In E_Vault::accounts_set_password(), we are calling new without a corresponding delete. Thus, each call to change a password leaks a few bytes of memory. Since this code was derived from the non-Intel SGX code path, a review of Vault.cpp reveals the exact same problem.</p>
<p>After fixing the memory leak, we run our test again and obtain the results shown in Figure 12:</p>
<p><code>The command line is: "cli native Test App.exe ".<br />
Enclave: "Enclave.signed.dll"<br />
[Peak stack use]: 0x2KB<br />
[Peak heap use]: 0x4KB </code><br /><strong>Figure 12.</strong> <em>EMMT output after fixing the memory leak.</em></p>
<p>This takes us back to our original heap usage of 4 KB.</p>
<p>We aren’t done, however. This is the <em>base</em> usage for a handful of entries, all with reasonable string lengths, but our vault can actually store much longer strings—up to 64 KB each, for the account name, URL, login name, and password. That means each account could require 256 KB, and with eight accounts total that means the vault could be up to 2 MB in memory.</p>
<p>How much memory we want to allocate to the enclave is now a judgement call. Realistically, users are probably not going to enter 65,000+ characters into any of the fields, so 2 MB of heap space for the highly unlikely, worst-case scenario seems excessive. If each field only stored 80 bytes, which is still a lot, the total storage need would be under 3 KB. To be safe, we’ll allocate an additional 4 KB to the heap above what the EMMT measures, which brings it to 8 KB. The stack is given the minimum of 4 KB. The final enclave settings are shown in Figure 13:</p>
<p style="text-align:center"><img alt="Final enclave settings" src="/sites/default/files/managed/0f/75/final-inclave.png" /><br /><strong>Figure 13. </strong><em>Final enclave settings for the Tutorial Password Manager.</em></p>
<p>Our enclave is now using only a fraction of the EPC that was allocated to it by the default configuration.</p>
<p>If we were building a commercially viable password manager, one that could have an unlimited number of accounts, we’d need a different design strategy for the application since the fixed heap size means an enclave’s memory footprint cannot grow without bound. Our enclave would not be able to store the entire password database unencrypted in memory, and would instead have to implement some form of just-in-time processing, where accounts were only decrypted as they were needed.</p>
<h2>Summary</h2>
<p>The Intel SGX SDK includes tools to aid in the development and debugging of Intel SGX enclaves, and in particular to address the unique challenges presented by the security model. Production applications must not be inspectable, but debuggers are a critical tool in the software development lifecycle, and Intel provides a solution in the Intel SGX Debugger. Special instructions in the Intel SGX instruction set allow developers to use the Intel SGX Debugger on debug-mode enclaves while denying the same to production applications. Additionally, developers are encouraged to minimize the memory footprint of their enclaves because the EPC is a shared resource. The EMMT gives developers the information they need to appropriately size their stack and heap allocations. The Intel SGX SDK provides a complete development ecosystem with libraries, APIs, and tools for aiding development, debugging, and management of enclaves.</p>
<h2>Sample Code</h2>
<p>The code sample for this part of the series builds against the Intel SGX SDK version 1.8 using Microsoft Visual Studio 2015.</p>
<h2>Coming Up Next</h2>
<p>In Part 11 of the series, we’ll prepare our Tutorial Password Manager for deployment by creating an installation package. Stay tuned!</p>
Thu, 05 Oct 2017 12:00:17 -0700John M. (Intel)746496Intel® Software Guard Extensions Tutorial Part 9: Power Events and Data Sealing https://software.intel.com/en-us/articles/intel-sgx-tutorial-part-9-power-events-and-data-sealing
<p><a class="button-highlight" href="/protected-download/676750/737211" rel="nofollow">Download</a> [ZIP 598KB]</p>
<p>In part 9 of the <a href="https://software.intel.com/en-us/sgx">Intel® Software Guard Extensions (Intel® SGX)</a> tutorial series we’ll address some of the complexities surrounding the suspend and resume power cycle. Our application needs to do more than just <em>survive</em> power transitions: it must also provide a smooth user experience without compromising overall security. First, we’ll discuss what happens to enclaves when the system resumes from the sleep state and provide general advice on how to manage power transitions in an Intel SGX application. We’ll examine the data sealing capabilities of Intel SGX and show how they can help smooth the transitions between power states, while also pointing out some of the serious pitfalls that can occur when they are used improperly. Finally, we’ll apply these techniques to the Tutorial Password Manager in order to create a smooth user experience.</p>
<p>You can find a list of all the published tutorials in the article <a href="https://software.intel.com/en-us/articles/introducing-the-intel-software-guard-extensions-tutorial-series">Introducing the Intel® Software Guard Extensions Tutorial Series</a>.</p>
<p>Source code is provided with this installment of the series.</p>
<h2>Suspend, Hibernate, and Resume</h2>
<p>Applications must be able to survive a sleep and resume cycle. When the system resumes from suspend or hibernation, applications should return to their previous state, or, if necessary, create a new state specifically to handle the wake event. What applications <em>shouldn’t</em> do is become unstable or crash as a direct result of that change in the power state. Call this the “rule zero” of managing power events.</p>
<p>Most applications don’t actually need special handling for these events. When the system suspends, the application state is preserved because RAM is still powered on. When the system hibernates, the RAM is saved to a special hibernation file on disk, which is used to restore the system state when it’s powered back on. You don’t need to add code to enable or take advantage of this core feature of the OS. There are two notable exceptions, however:</p>
<ul><li>Applications that rely on physical hardware that isn’t guaranteed to be preserved across power events, such as CPU caches.</li>
<li>Scenarios where possible changes to the system context can affect program logic. For example, a location-based application can be moved hundreds of miles while it’s sleeping and would need to re-acquire its location. An application that works with sensitive data may choose to guard against theft by reprompting the user for his or her password.</li>
</ul><p>Our Tutorial Password Manager actually falls into <em>both</em> categories. Certainly, if a laptop running our password manager is stolen, the thief would potentially have access to the victim’s passwords until they explicitly closed the application or locked the vault. The first category, though, may be less obvious: Intel SGX is a hardware feature that is not preserved across power events.</p>
<p>We can demonstrate this by running the Tutorial Password Manager, unlocking the vault, suspending the system, waking it back up, and then trying to read a password or edit one of the accounts. Follow those sequences, and you’ll get one of the error dialogs shown in Figure 1 or Figure 2.</p>
<p style="text-align:center"><img src="/sites/default/files/managed/ae/3d/intel-software-guard-extensions-part-9-power-events-data-sealing-fig01.png" /></p>
<p style="text-align:center"><strong>Figure 1.</strong> Error received when attempting to edit an account after resuming from sleep.</p>
<p style="text-align:center"><img src="/sites/default/files/managed/bf/a3/intel-software-guard-extensions-part-9-power-events-data-sealing-fig02.png" /></p>
<p style="text-align:center"><strong>Figure 2.</strong> Error received when attempting to view an account password after resuming from sleep.</p>
<p>As currently written, the Tutorial Password Manager violates rule zero: it becomes unstable after resuming from a sleep operation. The application needs special handling for power events.</p>
<h2>Enclaves and Power Events</h2>
<p>When a processor leaves S0 or S1 for a lower-power state, the enclave page cache (EPC) is destroyed: all EPC pages are erased along with their encryption keys. Since enclaves store their code and data in the EPC, when the EPC goes away the enclaves go with it. This means that enclaves do not survive power events that take the system to state S2 or lower.</p>
<p>Table 1 provides a summary of the power states.</p>
<p style="text-align:center"><strong>Table 1.</strong> CPU power states</p>
<table border="1" class="grey-alternating-rows"><tbody><tr><td>
<p><strong>State</strong></p>
</td>
<td>
<p><strong>Description</strong></p>
</td>
</tr><tr><td>
<p><strong>S0</strong></p>
</td>
<td>
<p>Active run state. The CPU is executing instructions, and background tasks are running even if the system appears idle and the display is powered off.</p>
</td>
</tr><tr><td>
<p><strong>S1</strong></p>
</td>
<td>
<p>Processor caches are flushed, CPU stops executing instructions. Power to CPU and RAM is maintained. Devices may or may not power off. This is a high-power standby state, sometimes called “power on suspend.”</p>
</td>
</tr><tr><td>
<p><strong>S2</strong></p>
</td>
<td>
<p>CPU is powered off. CPU context and contents of the system cache are lost.</p>
</td>
</tr><tr><td>
<p><strong>S3</strong></p>
</td>
<td>
<p>RAM is powered on to preserve its contents. A standby or sleep state.</p>
</td>
</tr><tr><td>
<p><strong>S4</strong></p>
</td>
<td>
<p>RAM is saved to nonvolatile storage in a hibernation file before powering off. When powered on, the hibernation file is read in to restore the system state. A hibernation state.</p>
</td>
</tr><tr><td>
<p><strong>S5</strong></p>
</td>
<td>
<p>“Soft off.” The system is off but some components are powered to allow a full system power-on via some external event, such as Wake-on-LAN, a system management component, or a connected device.</p>
</td>
</tr></tbody></table><p>Power state S1 is not typically seen on modern systems, and state S2 is uncommon in general. Most CPUs go to power state S3 when put in “sleep” mode and drop to S4 when hibernating to disk.</p>
<p>The Windows* OS provides a mechanism for applications to subscribe to wakeup events, but that won’t help any ECALLs that are in progress when the power transition occurs (and, by extension, any OCALLs either since they are launched from inside of ECALLs). When the enclave is destroyed, the execution context for the ECALL is destroyed with it, any nested OCALLs and ECALLs are destroyed, and the outer-most ECALL immediately returns with a status of SGX_ERROR_ENCLAVE_LOST.</p>
<p>It is important to note that any OCALLs that are in progress are destroyed without warning, which means any changes they are making in unprotected memory will potentially be incomplete. Since unprotected memory is maintained or restored when resuming from the S3 and S4 power states, it is important that developers use reliable and robust procedures to prevent partial write corruptions. Applications must not end up in an indeterminate or invalid state when power resumes.</p>
<h3>General Advice for Managing Power Transitions</h3>
<p>Planning for power transitions begins before a sleep or hibernation event occurs. Decide how extensive the enclave recovery needs to be. Should the application be able to pick up exactly where it left off without user intervention? Will it resume interrupted tasks, restart them, or just abort? Will the user interface, if any, reflect the change in state? The answers to these questions will drive the rest of the application design. As a general rule, the more autonomous and seamless the recovery is, the more complex the program logic will need to be.</p>
<p>An application may also have different levels of recovery at different points. Some stages of an application may be easier to seamlessly recover from than others, and in some execution contexts it may not make sense or even be good security practice to attempt a seamless recovery at all.</p>
<p>Once the overall enclave recovery strategy has been identified, the process of preparing an enclave for a power event is as follows:</p>
<ol><li>Determine the minimal state information and data that needs to be saved in order to reconstruct the enclave.</li>
<li>Periodically seal the state information and save it to unprotected memory (data sealing is discussed below). The sealed state data can be sent back to the main application as an [out] pointer parameter to an ECALL, or the ECALL can make an OCALL specifically to save state data.</li>
<li>When an SGX_ERROR_ENCLAVE_LOST code is returned by an ECALL, explicitly destroy the enclave and then recreate it. <strong>It is strongly recommended that applications explicitly destroy the enclave with a call to <em>sgx_enclave_destroy</em>()</strong>.</li>
<li>Restore the enclave state using an ECALL that is designed to do so.</li>
</ol><p>It is important to save the enclave state to untrusted memory <em>before</em> a power transition occurs. Even if the OS is able to send an event to an application when it is about to enter a standby mode, there are no guarantees that the application will have sufficient time to act before the system physically goes to sleep.</p>
<h2>Data Sealing</h2>
<p>When an enclave needs to preserve data across instantiations, either in preparation for a power event or between executions of the parent application, it needs to send that data out to untrusted memory. The problem with untrusted memory, however, is exactly that: it is untrusted. It is neither encrypted nor integrity checked, so any data sent outside the enclave in the clear is potentially leaking secrets. Furthermore, if that data were to be modified in untrusted memory, future instantiations of the enclave would not be able to detect that the modification occurred.</p>
<p>To address this problem, Intel SGX provides a capability called data sealing. When data is sealed, it is encrypted with advanced encryption standard (AES) in Galois/Counter Mode (GCM) using a 128-bit key that is derived from CPU-specific key material and some additional inputs, guided by one of two key policies. The use of AES-GCM provides both confidentiality of the data being sealed and integrity checking when the data is read back in and unsealed (decrypted).</p>
<p>As mentioned above, the key used in data sealing is derived from several inputs. The two key policies defined by data sealing determine what those inputs are:</p>
<ul><li><strong>MRSIGNER</strong>. The encryption key is derived from the CPU’s key material, the security version number (SVN), and the enclave signing key used by the developer. Data sealed using MRSIGNER can be unsealed by other enclaves on that same system that originate from the same software vendor (enclaves that share the same signing key). The use of an SVN allows enclaves to unseal data that was sealed by previous versions of an enclave, but prevents older enclaves from unsealing data from newer versions. It allows enclave developers to enforce software version upgrades.</li>
<li><strong>MRENCLAVE</strong>. The encryption key is derived from the CPU’s key material and the enclave’s cryptographic signature. Data signed with the MRENCLAVE policy can only be unsealed by that exact enclave on that system.</li>
</ul><p>Note that the CPU is a common component in the two key policies. Each processor has some random, hardware-based key material—physical circuitry on the processor—which is built into it as part of the manufacturing process. This ensures that data sealed by an enclave on one CPU cannot be unsealed by enclaves on another CPU. Each CPU will result in a different signing key, even if all other aspects of the signing policy (enclave measurement, enclave signing key, SVN) are the same.</p>
<p>The data sealing and unsealing API is really a set of convenience functions. They provide a high-level interface to the underlying AES-GCM encryption and 128-bit key derivation functions.</p>
<p>Once data has been sealed in the enclave, it can be sent out to untrusted memory and optionally written to disk.</p>
<h3>Caveats</h3>
<p>There is a caveat with data sealing, though, and it has significant security implications. Your enclave API needs to include an ECALL that will take sealed data as an input and then unseal it. <strong>However, Intel SGX does not authenticate the calling application, so you cannot assume that only your application is loading your enclave.</strong> This means that your enclave can be loaded and executed by <em>anyone</em>, even applications you didn’t write. As you might recall from Part 1, enclave applications are divided into two parts: the trusted part, which is made up of the enclaves, and the untrusted part, which is the rest of the application. These terms, “trusted” and “untrusted,” are chosen deliberately.</p>
<p>Intel SGX cannot authenticate the calling application because this would require a trusted execution chain that runs from system power-on all the way through boot, the OS load, and launching the application. This is far outside the scope of Intel SGX, which limits the trusted execution environment to just the enclaves themselves. Because there’s no way for the enclave to validate the caller, each enclave must be written defensibly. <strong>Your enclave cannot make any assumptions about the application that has called into it.</strong> An enclave must be written under the assumption that <em>any</em> application can load it and execute its API, and that its ECALLs can be executed in <em>any </em>order.</p>
<p>Normally this is not a significant constraint, but sealing and unsealing data complicates matters significantly because both the sealed data and the means to unseal it are exposed to arbitrary applications. <strong>The enclave API must not allow applications to use sealed data to bypass security mechanisms.</strong></p>
<p>Take the following scenario as an example: A file encryption program wants to save end users the hassle of re-entering their password every time the application runs, so it seals their password using the data sealing functions and the MRENCLAVE policy, and then writes the sealed data to disk. When the application starts, it looks for the sealed data file, and if it’s present, reads it in and makes an ECALL to unseal the data and restore the user’s password into the enclave.</p>
<p>The problems with this hypothetical application are two-fold:</p>
<ul><li>It assumes that it is the only application that will ever load the enclave.</li>
<li>It doesn’t authenticate the end user when the data is unsealed.</li>
</ul><p>A malicious software developer can write their own application that loads the same enclave and follows the same procedure (looks for the sealed data file, and invokes the ECALL to unseal it inside the enclave). While the malicious application can’t expose the user’s password, it <em>can</em> use the enclave’s ECALLs to encrypt and decrypt the user’s files using their stored password, which is nearly as bad. The malicious user has gained the ability to decrypt files without having to know the user’s password at all!</p>
<p>A non-Intel SGX version of this same application that offered this same convenience feature would also be vulnerable, but that’s not the point. If the goal is to use Intel SGX features to harden the application’s security, those same features should not be undermined by poor programming practices!</p>
<h2>Managing Power Transitions in the Tutorial Password Manager</h2>
<p>Now that we understand how power events affect enclaves and know what tools are available to assist with the recovery process, we can turn our attention to the Tutorial Password Manager. As currently written, it has two problems:</p>
<ul><li>It becomes unstable after a power event.</li>
<li>It assumes the password vault should remain unlocked after the system resumes.</li>
</ul><p>Before we can solve the first problem we need to address the second one, and that means making some design decisions.</p>
<h3>Sleep and Resume Behavior</h3>
<p>The big decision that needs to be made for the Tutorial Password Manager is whether or not to lock the password vault when the system resumes from a sleep state.</p>
<p>The primary argument for locking the password vault after a sleep/resume cycle is to protect the password database in case the physical system is stolen while it’s suspended. This would prevent the thief from being able to access the password database after waking up the device. However, having the system lock the password vault immediately can also be a user interface friction: sometimes, aggressive power management settings cause a running system to sleep while the user is still in front of the device. If the user wakes the system back up immediately, they might be irritated to find that their password vault has been locked.</p>
<p>This issue really comes down to balancing user convenience against security, so the right approach is to give the user control over the application’s behavior. The default will be for the password vault to lock immediately upon suspend/resume, but the user can configure the application to wait up to 10 minutes after the sleep event before the vault is forcibly locked.</p>
<h3>Intel® Software Guard Extensions and Non-Intel Software Guard Extensions Code Paths</h3>
<p>Interestingly, the default behavior of the Intel SGX code path differs from that of the non-Intel SGX code path. Enclaves are destroyed during the sleep/resume cycle, which means that we <em>effectively</em> lock the password vault as a result. To give the user the illusion that the password vault never locked at all, we have to not only reload the vault file from disk, but also explicitly unlock it again <em>without</em> forcing the user to re-enter their password (this has some security implications, which we discuss below).</p>
<p>For the non-Intel SGX code path, the vault is just stored in regular memory. When the system resumes, system memory is unchanged and the application continues as normal. Thus, the default behavior is that an unlocked password vault remains unlocked when the system resumes.</p>
<h2>Application Design</h2>
<p>With the behavior of the application decided, we turn to the application design. Both code paths need to handle the sleep/resume cycle and place the vault in the correct state: locked or unlocked.</p>
<h3>The Non-Intel Software Guard Extensions Code Path</h3>
<p>This is the simpler of the two code paths. As mentioned above, the non-Intel SGX code path will, by default, leave the password vault unlocked if it was unlocked when the system went to sleep. When the system resumes it only needs to see how long it slept: if the sleep time exceeds the maximum configured by the user, the password vault should be explicitly locked.</p>
<p>To keep track of the sleep duration, we’ll need a periodic heartbeat that records the current time. This time will serve as the “sleep start” time when the system resumes. For security, the heartbeat time will be encrypted using the database key.</p>
<h3>The Intel Software Guard Extensions Code Path</h3>
<p>No matter how the application is configured, the system will need code to recreate the enclave and reopen the password vault. This will put the vault in the locked state.</p>
<p>The application will then need to see how long it has been sleeping. If the sleep time was less than the maximum configured by the user, the password vault needs to be explicitly unlocked without prompting the user for his or her master passphrase. In order to do that the application needs the passphrase, and that means the passphrase must be saved to untrusted memory so that it can be read back in when the system is restored.</p>
<p>The only safe way to save a secret to untrusted memory is to use data sealing, but this presents a significant security issue: As mentioned previously, our enclave can be loaded by <em>any</em> application, and the same ECALL that is used to unseal the master password will be available for anyone to use. Our password manager application exposes secrets to the end user (their passwords), and the master password is the only means of authenticating the user. The point of keeping the password vault unlocked after the sleep/resume cycle is to prevent the user from having to authenticate. That means we are creating a logic flow where a malicious user could potentially use our enclave’s API to unseal the user’s master password and then extract their account and password data.</p>
<p>In order to mitigate this risk, we’ll do the following:</p>
<ul><li>Data will be sealed using the MRENCLAVE policy.</li>
<li>Sealed data will be kept in memory only. Writing it to disk would increase the attack surface.</li>
<li>In addition to sealing the password, we’ll also include the process ID. The enclave will require that the process ID of the calling process match the one that was saved when unsealing the data. If they don’t match, the vault will be left in the locked state.</li>
<li>The current system time will be sealed periodically using a heartbeat function. This will serve as the “sleep start” time.</li>
<li>The sleep duration will be checked in the enclave.</li>
</ul><p>Note that verification logic must be in the enclave where it cannot be modified or manipulated.</p>
<p>This is not a perfect solution, but it helps. A malicious application would need to scrape the sealed data from memory, crash the user’s existing process, and then create new processes over and over until it gets one with the same process ID. It will have to do all of this before the lock timeout is reached (or take control of the system clock).</p>
<h3>Common Needs</h3>
<p>Both code paths will need some common infrastructure:</p>
<ul><li>A timer to provide the heartbeat. We’ll use a timer interval of 15 seconds.</li>
<li>An event handler that is called when the system resumes from a sleep state.</li>
<li>Safe handling for any potential race conditions, since wakeup events are asynchronous.</li>
<li>Code that updates the UI to reflect the “locked” state of the password vault</li>
</ul><h2>Implementation</h2>
<p>We won’t go over every change in the code base, but we’ll look at the major components and how they work.</p>
<h3>User Options</h3>
<p>The lock timeout value is set in the new Tools -&gt; Options configuration dialog, shown in Figure 3.</p>
<p style="text-align:center"><img src="/sites/default/files/managed/06/07/intel-software-guard-extensions-part-9-power-events-data-sealing-fig03.png" /></p>
<p style="text-align:center"><strong>Figure 3.</strong> Configuration options.</p>
<p>This parameter is saved immediately to the Windows registry under HKEY_LOCAL_USER and is loaded by the application on startup. If the registry value is not present, the lock timeout defaults to zero (lock the vault immediately after going to sleep).</p>
<p>The Intel SGX code path also saves this value in the enclave.</p>
<h3>The Heartbeat</h3>
<p>Figure 4 shows the declaration for the <strong>Heartbeat </strong>class which is ultimately responsible for recording the vault’s state information. The heartbeat is only run if state information is needed, however. If the user has set the lock timeout to zero, we don’t need to maintain state because we know to lock the vault immediately when the system resumes.</p>
<pre class="brush:cpp;">class PASSWORDMANAGERCORE_API Heartbeat {
class PasswordManagerCoreNative *nmgr;
HANDLE timer;
void start_timer();
public:
Heartbeat();
~Heartbeat();
void set_manager(PasswordManagerCoreNative *nmgr_in);
void heartbeat();
void start();
void stop();
};
</pre>
<p style="text-align:center"><strong>Figure 4.</strong> The Heartbeat class.</p>
<p>The <strong>PasswordManagerCoreNative </strong>class gains a <strong>Heartbeat</strong> object as a class member, and the <strong>Heartbeat</strong> object is initialized with a reference back to the containing <strong>PasswordManagerCoreNative</strong> object.</p>
<p>The <strong>Heartbeat</strong> class obtains a timer from <em>CreateTimerQueueTimer </em>and executes the callback function <em>heartbeat_proc</em> when the timer expires, as shown in Figure 5. The timer is sent a reference to the <strong>Heartbeat</strong> object, which in turn calls the <em>heartbeat</em> method in the <strong>Heartbeat</strong> class, which in turn calls the <em>heartbeat</em> method in <strong>PasswordManagerCoreNative </strong>and restarts the timer.</p>
<pre class="brush:cpp;">static void CALLBACK heartbeat_proc(PVOID param, BOOLEAN fired)
{
// Call the heartbeat method in the Heartbeat object
Heartbeat *hb = (Heartbeat *)param;
hb-&gt;heartbeat();
}
Heartbeat::Heartbeat()
{
timer = NULL;
}
Heartbeat::~Heartbeat()
{
if (timer == NULL) DeleteTimerQueueTimer(NULL, &amp;timer, NULL);
}
void Heartbeat::set_manager(PasswordManagerCoreNative *nmgr_in)
{
nmgr = nmgr_in;
}
void Heartbeat::heartbeat ()
{
// Call the heartbeat method in the native password manager
// object. Restart the timer unless there was an error.
if (nmgr-&gt;heartbeat()) start_timer();
}
void Heartbeat::start()
{
stop();
// Perform our first heartbeat right away.
if (nmgr-&gt;heartbeat()) start_timer();
}
void Heartbeat::start_timer()
{
// Set our heartbeat timer. Use the default Timer Queue
CreateTimerQueueTimer(&amp;timer, NULL, (WAITORTIMERCALLBACK)heartbeat_proc,
(void *)this, HEARTBEAT_INTERVAL_SECS * 1000, 0, 0);
}
void Heartbeat::stop()
{
// Stop the timer (if it exists)
if (timer != NULL) {
DeleteTimerQueueTimer(NULL, timer, NULL);
timer = NULL;
}
}
</pre>
<p style="text-align:center"><strong>Figure 5. </strong>The Heartbeat class methods and timer callback function.</p>
<p>The heartbeat method in the <strong>PasswordManagerCoreNative</strong> object maintains the state information. To prevent partial write corruption, it has a two-element array of state data and an index pointer to the current index (0 or 1). The new state information is obtained from:</p>
<ul><li>The new ECALL <em>ve_heartbeat </em>in the Intel SGX code path (by way of <em>ew_heartbeat</em> in EnclaveBridge.cpp).</li>
<li>The <strong>Vault</strong> method <em>heartbeat </em>in the non-Intel SGX code path.</li>
</ul><p>After the new state has been received, it updates the next element (alternating between elements 0 and 1) of the array, and then updates the index pointer. The last operation is our atomic update, ensuring that the state information is complete before we officially mark it as the “current” state.</p>
<h4>Intel Software Guard Extensions code path</h4>
<p>The <em>ve_heartbeat</em> ECALL simply calls the <em>heartbeat </em>method in the <strong>E_Vault </strong>object, as shown in Figure 6.</p>
<pre class="brush:cpp;">int E_Vault::heartbeat(char *state_data, uint32_t sz)
{
sgx_status_t status;
vault_state_t vault_state;
uint64_t ts;
// Copy the db key
memcpy(vault_state.db_key, db_key, 16);
// To get the system time and PID we need to make an OCALL
status = ve_o_process_info(&amp;ts, &amp;vault_state.pid);
if (status != SGX_SUCCESS) return NL_STATUS_SGXERROR;
vault_state.lastheartbeat = (sgx_time_t)ts;
// Storing both the start and end times provides some
// protection against clock manipulation. It's not perfect,
// but it's better than nothing.
vault_state.lockafter = vault_state.lastheartbeat + lock_delay;
// Saves us an ECALL to have to reset this when the vault is restored.
vault_state.lock_delay = lock_delay;
// Seal our data with the MRENCLAVE policy. We defined our
// struct as packed to support working on the address
// directly like this.
status = sgx_seal_data(0, NULL, sizeof(vault_state_t), (uint8_t *)&amp;vault_state, sz, (sgx_sealed_data_t *) state_data);
if (status != SGX_SUCCESS) return NL_STATUS_SGXERROR;
return NL_STATUS_OK;
}
</pre>
<p style="text-align:center"><strong>Figure 6.</strong> The heartbeat in the enclave.</p>
<p>It has to obtain the current system time and the process ID, and to do this we have added our first OCALL to the enclave, <em>ve_o_process_info</em>. When the OCALL returns, we update our state information and then call <em>sgx_seal_data</em> to seal it into the <em>state_data </em>buffer<em>.</em></p>
<p>One restriction of the Intel SGX seal and unseal functions is that they can only operate on enclave memory. That means the <em>state_data</em> parameter must be a marshaled data buffer when used in this manner. If you need to write sealed data to a raw pointer that references untrusted memory (one that is passed with the user_check parameter), you must first seal the data to an enclave-local data buffer and then copy it over.</p>
<p>The OCALL is defined in EnclaveBridge.cpp:</p>
<pre class="brush:cpp;">// OCALL to retrieve the current process ID and
// local system time.
void SGX_CDECL ve_o_process_info(uint64_t *ts, uint64_t *pid)
{
DWORD dwpid= GetCurrentProcessId();
time_t ltime;
time(&amp;ltime);
*ts = (uint64_t)ltime;
*pid = (uint64_t)dwpid;
}
</pre>
<p>Because the heartbeat runs asynchronously, two threads can enter the enclave at the same time. This means the number of Thread Control Structures (TCSs) allocated to the enclave must be increased from the default of 1 to 2. This can be done one of two ways:</p>
<ol><li>Right-click the Enclave project, select Intel SGX Configuration -&gt; Enclave Settings to bring up the configuration window, and then set Thread Number to 2 (see Figure 7).</li>
<li>Edit the Enclave.config.xml file in the Enclave project directly, and then change the &lt;TCSNum&gt; parameter to 2.</li>
</ol><p style="text-align:center"><img src="/sites/default/files/managed/14/99/intel-software-guard-extensions-part-9-power-events-data-sealing-fig07.png" /></p>
<p style="text-align:center"><strong>Figure 7.</strong> Enclave settings dialog.</p>
<h3>Detecting Suspend and Resume Events</h3>
<p>A suspend and resume cycle will destroy the enclave, and that will be detected by the next ECALL. However, we shouldn’t rely on this mechanism to perform enclave recovery, because we need to act as soon as the system wakes up from the sleep state. That means we need an event listener to receive the power state change messages that are generated by Windows.</p>
<p>The best place to capture these is in the user interface layer. In addition to performing the enclave recovery, we must be able to lock the password vault if the system was in the sleep state longer than maximum sleep time set in the user options. When the vault is locked, the user interface also needs to be updated to reflect the new vault state.</p>
<p>One limitation of the Windows Presentation Foundation* is that it does not provide event hooks for power-related messages. The workaround is to hook in to the message handler for the underlying window handle. Our main application window and all of our dialog windows need a listener so that we can gracefully close each one.</p>
<p>The hook procedure for the main window is shown in Figure 8.</p>
<pre class="brush:cpp;">private IntPtr Main_Power_Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
UInt16 pmsg;
// C# doesn't have definitions for power messages, so we'll get them via C++/CLI. It returns a
// simple UInt16 that defines only the things we care about.
pmsg= PowerManagement.message(msg, wParam, lParam);
if ( pmsg == PowerManagementMessage.Suspend )
{
mgr.suspend();
handled = true;
} else if (pmsg == PowerManagementMessage.Resume)
{
int vstate = mgr.resume();
if (vstate == ResumeVaultState.Locked) lockVault();
handled = true;
}
return IntPtr.Zero;
}
</pre>
<p style="text-align:center"><strong>Figure 8.</strong> Message hook for the main window.</p>
<p>To get at the messages, the handler must dip down to native code. This is done using the new <strong>PowerManagement</strong> class, which defines a static function called <em>message</em>, shown in Figure 9. It returns one of four values:</p>
<table border="0" class="grey-alternating-rows"><tbody><tr><td>
<p><strong>PWR_MSG_NONE</strong></p>
</td>
<td>
<p>The message was not a power event.</p>
</td>
</tr><tr><td>
<p><strong>PWR_MSG_OTHER</strong></p>
</td>
<td>
<p>The message was power-related, but not a suspend or resume message.</p>
</td>
</tr><tr><td>
<p><strong>PWR_MSG_RESUME</strong></p>
</td>
<td>
<p>The system has woken up from a low-power or sleep state.</p>
</td>
</tr><tr><td>
<p><strong>PWR_MSG_SUSPEND</strong></p>
</td>
<td>
<p>The system is suspending to a low-power state.</p>
</td>
</tr></tbody></table><pre class="brush:cpp;">UINT16 PowerManagement::message(int msg, IntPtr wParam, IntPtr lParam)
{
INT32 subcode;
// We only care about power-related messages
if (msg != WM_POWERBROADCAST) return PWR_MSG_NONE;
subcode = wParam.ToInt32();
if ( subcode == PBT_APMRESUMEAUTOMATIC ) return PWR_MSG_RESUME;
else if (subcode == PBT_APMSUSPEND ) return PWR_MSG_SUSPEND;
// Don't care about other power events.
return PWR_MSG_OTHER;
}
</pre>
<p style="text-align:center"><strong>Figure 9.</strong> The message listener.</p>
<p>We actually listen for both suspend and resume messages here, but the suspend handler does very little work. When a system is transitioning to a sleep state, an application has less than 2 seconds to act on the power message. All we do with the sleep message is stop the heartbeat. This isn’t strictly necessary, and is just a precaution against having a heartbeat execute while the system is suspending.</p>
<p>The resume message is handled by calling the <em>resume </em>method in <strong>PasswordManagerCore</strong>. It’s job is to figure out whether the vault should be locked or unlocked. It does this by checking the current system time against the saved vault state (if any). If there’s no state, or if the system has slept longer than the maximum allowed, it returns <code>ResumeVaultState.Locked</code>.</p>
<h3>Restoring the Enclave</h3>
<p>In the Intel SGX code path, the enclave has to be recreated before the enclave state information can be checked. The code for this is shown in Figure 10.</p>
<pre class="brush:cpp;">bool PasswordManagerCore::restore_vault(bool flag_async)
{
bool got_lock= false;
int rv;
// Only let one thread do the restore if both come in at the
// same time. A spinlock approach is inefficient but simple.
// This is OK for our application, but a high-performance
// application (or one with a long-running work loop)
// would want something else.
try {
slock.Enter(got_lock);
if (_nlink-&gt;supports_sgx()) {
bool do_restore = true;
// This part is only needed for enclave-based vaults.
if (flag_async) {
// If we are entering as a result of a power event,
// make sure the vault has not already been restored
// by the synchronous/UI thread (ie, a failed ECALL).
rv = _nlink-&gt;ping_vault();
if (rv != NL_STATUS_LOST_ENCLAVE) do_restore = false;
// If do_store is false, then we'll also use the
// last value of rv_restore as our return value.
// This will tell us whether or not we should lock the
// vault.
}
if (do_restore) {
// If the vaultfile isn't open then we are locked or hadn't
// been opened to be begin with.
if (!vaultfile-&gt;is_open()) {
// Have we opened a vault yet?
if (vaultfile-&gt;get_vault_path()-&gt;Length == 0) goto restore_error;
// We were explicitly locked, so reopen.
rv = vaultfile-&gt;open_read(vaultfile-&gt;get_vault_path());
if (rv != NL_STATUS_OK) goto restore_error;
}
// Reinitialize the vault from the header.
rv = _vault_reinitialize();
if (rv != NL_STATUS_OK) goto restore_error;
// Now, call to the native object to restore the vault state.
rv = _nlink-&gt;restore_vault_state();
if (rv != NL_STATUS_OK) goto restore_error;
// The database password was restored to the vault. Now restore
// the vault, itself.
rv = send_vault_data();
restore_error:
restore_rv = (rv == NL_STATUS_OK);
}
}
else {
rv = _nlink-&gt;check_vault_state();
restore_rv = (rv == NL_STATUS_OK);
}
slock.Exit(false);
}
catch (...) {
// We don't need to do anything here.
}
return restore_rv;
}
</pre>
<p style="text-align:center"><strong>Figure 10.</strong> The <em>restore_vault</em>() method.</p>
<p>The enclave and vault are reinitialized from the vault data file, and the vault state is restored using the method <em>restore_vault_state</em> in <strong>PasswordManagerCoreNative.</strong></p>
<h4>Which Thread Restores the Vault State?</h4>
<p>The Tutorial Password Manager can have up to three threads executing at any given time. They are:</p>
<ul><li>The main UI</li>
<li>The heartbeat</li>
<li>The power event handler</li>
</ul><p>Only one of these threads should be responsible for actually restoring the enclave, but it is possible that both the heartbeat and the main UI thread are in the middle of an ECALL when a power event occurs. In that case, both ECALLs will fail with the error code SGX_ERR_ENCLAVE_LOST while the power event handler is executing. Given this potential race condition, it’s necessary to decide which thread is given the job of enclave recovery.</p>
<p>If the lock timeout is set to zero, there won’t be a heartbeat thread at all, so it doesn’t make sense to put enclave recovery logic there. If the heartbeat ECALL returns SGX_ERR_ENCLAVE_LOST, it simply stops the heartbeat and assumes other threads will be dealing with it.</p>
<p>That leaves the UI thread and the power event handler, and a good argument can be made that <em>both</em> threads need the ability to recover an enclave. The event handler will catch all suspend/resume cycles immediately, so it make sense to have enclave recovery happen there. However, as we pointed out earlier it is entirely possible for a power event to occur during an active ECALL on the UI thread, and there’s no reason to prevent <em>that</em> thread from starting the recovery, especially since it might occur before the power event message is received. This not only provides a safety net in case the event handler fails to execute for some reason, but it also provides a quick and easy retry loop for the operation.</p>
<p>Since we can’t have both of these threads run the recovery at the same time, we need to use locking to ensure that only the first thread to arrive is given the job. The second one simply waits for the first to finish.</p>
<p>It’s also possible that a failed ECALL will complete the recovery process before the event handler enters the recovery loop. To prevent the event handler from blindly repeating the enclave recovery procedure, we have added a quick test to make sure the enclave hasn’t already been recreated.</p>
<h4>Detection in the UI Thread</h4>
<p>The UI thread detects power events by looking for ECALLs that fail with SGX_ERR_LOST_ENCLAVE. The wrapper functions in EnclaveBridge.cpp automatically relaunch the enclave and pass the error NL_STATUS_ENCLAVE_RECREATED back up to the <strong>PasswordManagerCore</strong> object.</p>
<p>Each method in <strong>PasswordManagerCore</strong> handles this return code uniquely. Some methods, such as <em>initialize</em>, <em>initialize_from_header</em>, and <em>lock_vault</em> don’t actually have to restore state at all, but most of the others do and they call in to <em>restore_vault</em> as show in Figure 11.</p>
<pre class="brush:cpp;">int PasswordManagerCore::accounts_password_to_clipboard(UInt32 idx)
{
UINT32 index = idx;
int rv;
int tries = 3;
while (tries--) {
rv = _nlink-&gt;accounts_password_to_clipboard(index);
if (rv == NL_STATUS_RECREATED_ENCLAVE) {
if (!restore_vault()) {
rv = NL_STATUS_LOST_ENCLAVE;
tries = 0;
}
}
else break;
}
return rv;
}
</pre>
<p style="text-align:center"><strong>Figure 11.</strong> Detecting a power event on the main UI thread.</p>
<p>Here, the method gets three attempts to restore the vault before giving up. This retry count of three is an arbitrary limit: it’s not <em>likely</em> that we’ll have multiple power events in rapid succession but it’s possible. Though we don’t want to just give up after one attempt, we also don’t want to loop forever in case there’s a system issue that prevents the enclave from ever being recreated.</p>
<h3>Restoring and Checking State</h3>
<p>The last step is to examine the state data for the vault and determine whether the vault should be locked or unlocked. In the Intel SGX code path, the sealed state data is sent into the enclave where it is unsealed, and then compared to current system data obtained from the OCALL <em>ve_o_process_info</em>. This method, <em>restore_state</em>, is shown in Figure 12.</p>
<pre class="brush:cpp;">int E_Vault::restore_state(char *state_data, uint32_t sz)
{
sgx_status_t status;
vault_state_t vault_state;
uint64_t now, thispid;
uint32_t szout = sz;
// First, make an OCALL to get the current process ID and system time.
// Make these OCALLs so that the parameters aren't be supplied by the
// ECALL (which would make it trivial for the calling process to fake
// this information)
status = ve_o_process_info(&amp;now, &amp;thispid);
if (status != SGX_SUCCESS) {
// Zap the state data.
memset_s(state_data, sz, 0, sz);
return NL_STATUS_SGXERROR;
}
status = sgx_unseal_data((sgx_sealed_data_t *)state_data, NULL, 0, (uint8_t *)&amp;vault_state, &amp;szout);
// Zap the state data.
memset_s(state_data, sz, 0, sz);
if (status != SGX_SUCCESS) return NL_STATUS_SGXERROR;
if (thispid != vault_state.pid) return NL_STATUS_PERM;
if (now &lt; vault_state.lastheartbeat) return NL_STATUS_PERM;
if (now &gt; vault_state.lockafter) return NL_STATUS_PERM;
// Everything checks out. Restore the key and mark the vault as unlocked.
lock_delay = vault_state.lock_delay;
memcpy(db_key, vault_state.db_key, 16);
_VST_CLEAR(_VST_LOCKED);
return NL_STATUS_OK;
}
</pre>
<p style="text-align:center"><strong>Figure 12.</strong> Restoring state in the enclave.</p>
<p>Note that unsealing data is programmatically simpler than sealing it: the key derivation and policy information is embedded in the sealed data blob. Unlike data sealing there is only one unseal function, <em>sgx_unseal_data,</em> and it takes fewer parameters than its counterpart.</p>
<p>This method returns NL_STATUS_OK if the vault is restored to the unlocked state, and NL_STATUS_PERM if it is restored to the locked state.</p>
<h3>Lingering Issues</h3>
<p>The Tutorial Password Manager as currently implemented still has issues that need to be addressed.</p>
<ul><li>There is still a race condition in the enclave recovery logic. Because the ECALL wrappers in EnclaveBridge.cpp immediately recreate the enclave before returning an error code to the <strong>PasswordManagerCore </strong>layer, it is possible for the power event handler thread to enter the <em>restore_vault </em>method after the enclave has been recreated but before the enclave recovery has completed. This can cause the power event handler to return the wrong status to the UI layer, placing the UI in the “locked” or “unlocked” state incorrectly.</li>
<li>We depend on the system clock when validating our state data, but the system clock is actually untrusted. A malicious user can manipulate the time in order to force the password vault into an unlocked state when the system wakes up (this can be addressed by using trusted time, instead).</li>
</ul><h2>Summary</h2>
<p>In order to prevent cold boot attacks and other attacks against memory images in RAM, Intel SGX destroys the Enclave Page Cache whenever the system enters a low-power state. However, this added security comes at a price: software complexity that can’t be avoided. All real-world Intel SGX applications need to plan for power events and incorporate enclave recovery logic because failing to do so will lead to runtime errors during the application’s execution.</p>
<p>Power event planning can rapidly escalate the application’s level of sophistication. The user experience needs of the Tutorial Password Manager took us from a single-threaded application with relatively simple constructs to one with multiple, asynchronous threads, locking, and atomic memory updates via simple journaling. As a general rule, seamless enclave recovery requires careful design and a significant amount of added program logic.</p>
<h2>Sample Code</h2>
<p>The code sample for this part of the series builds against the Intel SGX SDK version 1.7 using Microsoft Visual Studio* 2015.</p>
<h3>Release Notes</h3>
<ul><li>Running a mixed-mode Intel SGX application under the debugger in Visual Studio will cause an exception to be thrown if a power event is triggered. The exception occurs when an ECALL detects the lost enclave and returns SGX_ERROR_LOST_ENCLAVE.</li>
<li>The non-Intel SGX code path was updated to use Microsoft’s DPAPI to store the database encryption key. This is a better solution than the in-memory XOR’ing.</li>
</ul><h2>Coming Up Next</h2>
<p>In <a href="https://software.intel.com/en-us/articles/intel-software-guard-extensions-tutorial-series-part-10-enclave-analysis-and-debugging">Part 10 of the series</a>, we’ll discuss debugging mixed-mode Intel SGX applications with Visual Studio and the Enclave Memory Measurement Tool. Stay tuned!</p>
Thu, 22 Jun 2017 15:12:28 -0700John M. (Intel)737211Getting Started with Intel® Software Guard Extensions SDK for Microsoft* Windows* OShttps://software.intel.com/en-us/articles/getting-started-with-sgx-sdk-for-windows
<p>Intel® Software Guard Extensions (Intel® SGX) is an Intel technology for application developers seeking to protect select code and data from disclosure or modification. Intel SGX makes such protections possible through the use of enclaves. Enclaves are protected areas of execution. Application code can be put into an enclave through special instructions and software made available to developers by the Intel SGX SDK.</p>
<p>Intel Software Guard Extensions has the following features:</p>
<ul><li>Hardware enforced security</li>
<li>Remote attestation support</li>
<li>Data sealing</li>
</ul><p>This article provides an overview of the process for enabling applications with Intel SGX using Microsoft* Visual Studio* 2015 on a 64-bit Microsoft Windows* OS. The article covers product contents, configuring the Intel SGX development system, defining Intel SGX project settings in Visual Studio, building sample applications, creating new enclave projects, and signing enclaves. A discussion of typical errors and their resolution is also provided at the end.</p>
<p><strong>Note:</strong> Intel Software Guard Extensions SDK is offered for evaluation purposes only. If you would like to deliver a production-quality application using Intel SGX, contact the <a href="mailto:sgx_program@intel.com?subject=Getting%20Started%20with%20Intel%20SGX%20for%20Windows" rel="nofollow">Intel® SGX Program</a> for more information about a production license.</p>
<p>If you are already familiar with the <em>basics</em> of Intel SGX application development and want a deeper understanding the kinds of design decisions you may have to make when developing your own application, jump into the Intel SGX Tutorial Series, starting with: <a href="https://software.intel.com/articles/intel-software-guard-extensions-tutorial-part-1-foundation">https://software.intel.com/articles/intel-software-guard-extensions-tutorial-part-1-foundation</a>.</p>
<h2>Product Contents</h2>
<p>Intel Software Guard Extensions SDK comprises the following main components:</p>
<ul><li>Trusted libraries includes standard C library, C++ runtime support, C++ STL, and so on.</li>
<li>Development tools includes edger8r, signing tool, Microsoft Visual Studio IDE plug-in, and so on.</li>
<li>Sample projects</li>
</ul><h2>Prerequisites</h2>
<p>Required Software:</p>
<ul><li>64-bit Microsoft Windows OS</li>
<li>Microsoft Visual Studio 2015</li>
<li>Intel Software Guard Extensions SDK</li>
</ul><p>See Intel Software Guard Extensions SDK for Windows* OS Release Notes for details.</p>
<p>Your development system must support Intel SGX (CPU and BIOS) if you want to execute your Intel SGX enabled applications on the same system where you build them. If you want to build Intel SGX enabled applications and run them on a different platform, or run them in simulation mode only, then your development system does not need to support Intel SGX. (But the execution system does need to support Intel SGX.) The discussion that follows assumes you want to build <em>and</em> run your enclave applications on the development platform.</p>
<h2>Configuring the Intel SGX development environment</h2>
<p>Intel SGX development environment must be configured properly to build Intel SGX applications. The first step is to check whether the system’s CPU supports Intel SGX. If the target system CPU does <em>not</em> support Intel SGX, there is no point in trying to configure the system BIOS/SW to support Intel SGX. (You can still build and debug Intel SGX applications in <em>Simulation</em> mode, but you can’t test/run them on actual system hardware unless your CPU/BIOS/SW stack supports Intel SGX.)</p>
<p>Developers can check the Intel website <a href="http://ark.intel.com/">http://ark.intel.com/</a>, to determine if the CPU in their target system supports the Intel SGX instruction set, first introduced in the 6<sup>th</sup> Generation Intel® Core<sup>TM</sup> processors. The website lists each CPU and whether or not they support Intel SGX.</p>
<h3>Configuring Intel SGX in BIOS</h3>
<p>After confirming CPU support for Intel SGX, check the system BIOS to see if Intel SGX is supported. While it’s likely that systems with an Intel SGX supported CPU will also support Intel SGX in the BIOS, it’s also good to check, as there may be some exceptions. This can be checked in either of two ways:</p>
<ul><li>Using the Intel-provided tool: Intel provides a tool to verify whether the target system (including the BIOS) supports Intel SGX and whether it is enabled. This can be verified by following the procedure at <a href="https://software.intel.com/en-us/articles/properly-detecting-intel-software-guard-extensions-in-your-applications">https://software.intel.com/en-us/articles/properly-detecting-intel-software-guard-extensions-in-your-applications</a>. The link to download the source code for the tool is provided at the end of that procedure and at: <a href="https://software.intel.com/sgx-sdk/download">https://software.intel.com/sgx-sdk/download</a>.</li>
<li>Navigating through BIOS menu (manually): The BIOS menu can be navigated manually to verify whether Intel SGX support is enabled.</li>
</ul><p>If Intel SGX is not supported in the BIOS, you can’t enable it, but you can still build and debug Intel SGX applications in <em>Simulation</em> mode.</p>
<h3>Manual BIOS Configuration</h3>
<p>The OEM for your system may have included an Intel reference BIOS for Intel SGX or may have included their own custom BIOS. If your system includes an Intel reference BIOS for Intel SGX, the steps that follow can be used to ensure Intel SGX is enabled. (If your system uses an OEM custom BIOS, the same <em>general</em> process can be followed, but the messages you see on the screen will be different.)</p>
<p>1. During system boot, type the keystroke(s) (usually a function key) to enter BIOS.</p>
<p>2. Navigate through the following menus:</p>
<p> <strong>Intel Advanced Menu</strong><strong>-&gt;CPU Configuration</strong><strong>-&gt;SW Guard Extensions (SGX) </strong></p>
<p>3. The BIOS displays the options that follow. (Not all system OEMs support all three options.)</p>
<p> <strong>Enabled</strong><br />
<strong>Software Controlled</strong><br />
<strong>Disabled</strong></p>
<p> These options are defined as follows:</p>
<p> <strong>Enabled</strong></p>
<p> If this option is set, Intel SGX is enabled and available for use by applications.</p>
<p> <strong>Note:</strong> If Enabled is set, <strong>Intel Advanced Menu</strong><strong>-&gt;CPU Configuration</strong><strong>-&gt;PRMRR</strong> must also be configured. (Some OEMs may automatically assign a PRMRR value when Intel SGX is enabled.) If the OEM supports PRMRR selection, set the value to 32 MB, 64 MB or 128 MB. The default option for the Intel reference BIOS is 128 MB.</p>
<p> <strong>Software Controlled</strong></p>
<p> If <strong>Software Controlled</strong> is set, your application must use the API for enabling Intel SGX mentioned in the <em>Intel SGX feature detection procedure</em> (link previously provided)<em>.</em></p>
<p> <strong>Note:</strong> Enabling Intel SGX via software opt-in may require a system reboot.</p>
<p> <strong>Disabled</strong></p>
<p> If <strong>Disabled</strong> is set, Intel SGX is explicitly disabled and it cannot be enabled through software applications. You should change this setting to <strong>Enabled</strong>. If <strong>Disabled</strong>, you can only build/run Intel SGX enabled applications in Simulation Mode. Also, the Intel SGX Platform Software (PSW) will not install.</p>
<p>4. After enabling Intel SGX, enter the keystrokes to <strong>Save and Exit</strong> the BIOS.</p>
<h3>Installing Development SW</h3>
<p>Install the software listed below. (Visual Studio must be installed before the Intel SGX SDK.)</p>
<ul><li>Full set of Intel Management Engine (ME) software components 11.5.0.1000 or later.</li>
<li>Microsoft Visual Studio 2015 (Professional or higher)
<ul><li>The Wizard requires Microsoft Visual C++ tools to be installed, which is no longer done by default in Visual Studio 2015. Please make sure the C++ tools are installed before using the Wizard to create an enclave project.</li>
</ul></li>
<li>Intel SGX SDK 1.8 or later</li>
<li>Intel SGX Platform Software (PSW) 1.8 or later</li>
</ul><p><strong>ME SW:</strong> The Intel ME software components that must be installed depend on the system's specific hardware and firmware features. You can determine the version of the ME SW in your system by checking the <strong>Control Panel</strong><strong>-&gt;Programs and Features</strong> list. If the version of ME in your system is not high enough, download and install the most current version from: <a href="https://downloadcenter.intel.com/download/26482/Intel-Management-Engine-Consumer-Driver">https://downloadcenter.intel.com/download/26482/Intel-Management-Engine-Consumer-Driver</a>. The Intel ME installer detects the system's capabilities and automatically installs the relevant drivers and applications.</p>
<p><strong>Visual Studio:</strong> Obtain the Professional Edition (or higher) from Microsoft at: <a href="https://msdn.microsoft.com/" rel="nofollow">https://msdn.microsoft.com</a>. Make sure you manually install the Microsoft Visual C++ tools after installing Visual Studio.</p>
<p><strong>Intel SGX SDK:</strong> The Intel SGX SDK from Intel is a collection of APIs, sample source code, libraries, and tools that enable the software developer to write and debug Intel SGX applications in C/C++. The SDK installs a Microsoft Visual Studio software wizard to aid in rapid development of Intel SGX enabled applications. This wizard can be used to create an enclave project with the proper settings to take advantage of the various components that are shipped with the Intel SGX SDK.</p>
<p><strong>Intel SGX PSW:</strong> The Intel SGX PSW provides the platform services, run-time components for attestation, and Intel SGX Driver for EPC memory allocation and de-allocation. The Intel SGX PSW exposes an API that Intel SGX applications should call prior to application initialization. The API <strong>sgx_enable_device</strong> provided by the Intel SGX PSW configures and enables the Intel SGX device if the platform has NOT been previously enabled. (The PSW will not install if Intel SGX is not supported by the CPU and supported/enabled in BIOS.)</p>
<p>The SDK and PSW can be obtained by first registering here: <a href="https://registrationcenter.intel.com/en/forms/?productid=2614">https://registrationcenter.intel.com/en/forms/?productid=2614</a>. Download and install both SW packages.</p>
<p>After the installation is done, check the <strong>Windows Control Panel</strong><strong>-&gt;Programs and Feature</strong> list to confirm the Intel SGX SW components were installed.</p>
<h3>Oops … out of order installation</h3>
<p>Microsoft Visual Studio <em>must</em> be installed before installing the Intel SGX SDK. If the Intel SGX SDK is installed before installing Visual Studio, the Intel SGX SDK Visual Studio software Wizard and Intel(R) SGX Debugger will <em>not</em> be embedded properly into Visual Studio. If this occurs, you will experience errors while building your Intel SGX enabled application and enclaves cannot be created.</p>
<p>If you find yourself in this situation, uninstall the Intel SGX SDK, then reinstall it.</p>
<h3>Project settings in Visual Studio</h3>
<p>Make sure the Visual Studio Project settings are configured properly before attempting to build any of the sample applications. The following steps make use of <strong>SampleEnclave</strong>, a small application that creates an enclave. (<strong>SampleEnclave</strong> is one of several sample applications installed with the SDK.)</p>
<p>Walk through the steps that follow to make sure the Visual Studio settings are configured to build applications. Important points are discussed at the appropriate step.</p>
<p>The following steps assume you are opening the sample solution as Admin from its default installation folder. Alternately, you can copy the sample solution to a folder in your user area.</p>
<p>1. Open Visual Studio, then open the <strong>SampleEnclave</strong> solution using the following menu sequence:</p>
<p> a. <strong>File</strong><strong>-&gt;Open-&gt;Project/Solution</strong></p>
<p> b. Navigate to <strong>C:\Program Files (x86)\Intel\IntelSGXSDK\src\SampleEnclave</strong></p>
<p> c. Click on <strong>SampleEnclave.sln</strong> to open the solution file</p>
<p> Your screen should open the solution as shown in Figure 1. The location of the <strong>Solution Explorer</strong> window on your screen may be different, depending on your Visual Studio layout preferences.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Intel SGX SDK for Windows Visual Studio Solution" title="Intel SGX SDK for Windows Visual Studio Solution" height="1000" width="1778" src="https://software.intel.com/sites/default/files/managed/e5/c6/get-started-sgx-sdk-win-vs-solution-1.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 1. Visual Studio with SampleEnclave solution open</strong></p>
<p>2. Check the Build configuration on the Visual Studio toolbar. Note that the Build configuration is set to <strong>Debug</strong> mode, as shown in Figure 2. Debug mode is the default mode for developing an Intel SGX enabled application.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Intel SGX SDK for Windows Visual Studio Debug Mode" title="Intel SGX SDK for Windows Visual Studio Debug Mode" height="410" width="746" src="https://software.intel.com/sites/default/files/managed/38/ee/get-started-sgx-sdk-win-vs-debug-mode-1.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 2. Verifying Debug mode in Visual Studio</strong></p>
<p>Here is a summary of the four build configurations:</p>
<p>The Intel SGX architecture supports two modes of operation for enclaves: Debug Mode and Production (non-debug) Mode. Production Mode enclaves have the full protection provided by the Intel SGX architecture, while Debug Mode enclaves have slightly less protection to support debug capabilities.</p>
<p>Traditionally, developers are familiar with two basic compilation profiles:</p>
<ul><li><strong>Debug:</strong> compiler optimizations are disabled and symbol information is saved. This mode is suitable for source-level debugging. Enclaves built in debug mode are launched in enclave-debug mode.</li>
<li><strong>Release:</strong> compiler optimizations are enabled and no symbol information is saved. This mode is suitable for production build, performance testing, and final product release. Enclaves built in this mode are launched in enclave-production (non-debug) mode.</li>
</ul><p>In addition, the Intel SGX SDK offers two more compilation profiles:</p>
<ul><li><strong>Pre-release:</strong> same as Release with regard to compiler optimizations and symbol information. However, the enclaves are launched in enclave-debug mode, suitable for performance testing.</li>
<li><strong>Simulation:</strong> builds the enclave without compiler optimizations and links the application with libraries that simulate the Intel SGX instructions. This allows the enclave to be run on any platform without Intel SGX.</li>
</ul><p>A more detailed discussion of Debug and Build Configurations is provided at: <a href="https://software.intel.com/sites/default/files/managed/e5/d8/intel-sgx-build-configuration.pdf">https://software.intel.com/sites/default/files/managed/e5/d8/intel-sgx-build-configuration.pdf</a>. You can also check the SDK Developer Guide and Developer Reference.</p>
<p>3. For both the <strong>App</strong> and <strong>Enclave</strong> application in the project, make sure the compiler and debugger settings are set. Right click on <strong>Project</strong><strong>-&gt;Properties</strong> to check the compiler selection. The default is Intel C++ 16.0 Compiler. If you have not purchased and installed the Intel compiler, change the <strong>Platform Toolset</strong> setting to the Visual Studio 2015 compiler as shown in Figure 3. Click <strong>Apply</strong> to save the new compiler choice.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Intel SGX SDK for Windows Visual Studio Setting Compiler" title="Intel SGX SDK for Windows Visual Studio Setting Compiler" height="761" width="1061" src="https://software.intel.com/sites/default/files/managed/99/ce/get-started-sgx-sdk-win-vs-set-compiler1.PNG" /></span></p>
</td>
</tr></tbody></table><div><strong>Figure 3. Selecting the compiler for the project</strong></div>
<p>4. While still in the <strong>Properties</strong> window, select <strong>Debugging</strong>. Verify that the <strong>Intel(R) SGX Debugger</strong> is selected and that the <strong>Working Directory</strong> is set to <strong>$(OutDir)</strong> as shown in Figure 4. These settings may already be configured properly. Select <strong>OK</strong> when done.</p>
<table align="center" border="1"><tbody><tr><td style="width:735px">
<p align="center"><span><img alt="Intel SGX SDK for Windows Visual Studio Setting Debugger" title="Intel SGX SDK for Windows Visual Studio Setting Debugger" height="760" width="1059" src="https://software.intel.com/sites/default/files/managed/6c/98/get-started-sgx-sdk-win-vs-set-debugger1.PNG" /></span></p>
</td>
</tr></tbody></table><div><strong>Figure 4. Verifying the Debugging and Working Directory settings for the project</strong></div>
<p>5. Select <strong>Build</strong><strong>-&gt;Build Solution</strong> <strong>(Cntl+Shift+B)</strong> to build <strong>SampleEnclave</strong>. If you experience any errors, refer to <em>Errors during application development</em> near the end of the paper.</p>
<p>6. When finished, select <strong>Debug</strong><strong>-&gt;Start Without Debugging (Cntl+F5)</strong> to run the sample application. The application starts and creates an enclave. Then it opens a command line window, as shown in Figure 5. Enter a character followed by <strong>&lt;Enter&gt;</strong>, or just press <strong>&lt;Enter&gt;</strong> to end the application.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Intel SGX SDK for Windows Visual Studio Running Sample Enclave" title="Intel SGX SDK for Windows Visual Studio Running Sample Enclave" height="485" width="783" src="https://software.intel.com/sites/default/files/managed/b2/fc/get-started-sgx-sdk-win-sample-enclave-running1.PNG" /></span></p>
</td>
</tr></tbody></table><div><strong>Figure 5. SampleEnclave running</strong></div>
<p>Once you can successfully build and run sample Intel SGX enabled applications, you know that your Visual Studio + Intel SGX SDK configuration is set up properly.</p>
<h2>Creating a new Enclave project</h2>
<p>The steps in this section describe how to create a <em>new</em> Intel SGX Enclave Project from scratch in Microsoft Visual Studio. These are steps you must perform each time you start work on a new Intel SGX enabled application in Visual Studio. The discussion that follows assumes you have a skeleton application. (Some code snippets are provided near the end if you want to use them instead of your own application.) The major steps are:</p>
<ul><li>Create the Intel(R) SGX Enclave Project</li>
<li>Configure the Enclave Settings</li>
<li>Import the EDL File into the untrusted application project</li>
</ul><h3>Create the enclave project</h3>
<p>The following steps explain how to create the enclave project. (You also need to create the untrusted application project like you typically do.)</p>
<p>1. In Visual Studio, select <strong>File-&gt;</strong><strong>New</strong><strong>-&gt;Project</strong>. The <strong>New Project</strong> dialog box opens.</p>
<p>2. Select <strong>Templates</strong><strong>-&gt;Visual C++</strong><strong>-&gt;Intel® SGX Enclave Project</strong> as shown in Figure 6.</p>
<p> a. Enter <strong>Name</strong>, <strong>Location</strong>, and <strong>Solution name</strong> in the respective fields like any other Visual Studio project.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Create Enclave" title="Getting Started with Intel SGX SDK for Windows Create Enclave" height="1000" width="1522" src="https://software.intel.com/sites/default/files/managed/3e/3c/get-started-sgx-sdk-win-vs-create-enclave-1.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 6. Creating an Intel SGX enclave project</strong></p>
<p>3. Click <strong>OK</strong>. The Intel® SGX SDK Project Wizard displays the default <strong>Enclave Settings</strong> window, as shown in Figure 7.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Enclave Settings 1" title="Getting Started with Intel SGX SDK for Windows Enclave Settings 1" height="522" width="719" src="https://software.intel.com/sites/default/files/managed/dc/48/get-started-sgx-sdk-win-vs-enclave-settings-1.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 7. Enclave project settings window</strong></p>
<p>4. If these settings are appropriate for your project, click <strong>Finish</strong>, to jump to the end of step 6. To make changes (or just to learn about the settings), click <strong>Next</strong>. The wizard displays the screen shown in Figure 8.</p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Enclave Settings 2" title="Getting Started with Intel SGX SDK for Windows Enclave Settings 2" height="957" width="1227" src="https://software.intel.com/sites/default/files/managed/ad/6e/get-started-sgx-sdk-win-vs-enclave-settings-2.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 8. Configuring enclave project settings</strong></p>
<p>5. Configure the Visual Studio enclave project settings. See the notes below for help.</p>
<p><strong>Project Type:</strong></p>
<ul><li>Enclave — Create an enclave project. This is likely your choice if you are creating your first enclave project.</li>
<li>Enclave library — Create a static library for an enclave project. This is the choice if you are creating an enclave library that could be shared across several applications.</li>
</ul><p><strong>Additional Libraries:</strong></p>
<ul><li>C++ 11 — Link to C++ 11 libraries. This is the choice if you are developing in C++. Uncheck this checkbox if you are writing in pure C. Note that the linking option to C++ 11 is grayed out when Enclave library is selected.
<ul><li>Note: If creating an enclave that uses a library, and <em>that</em> library uses C++, then when you create the enclave project you must select the C++11 option, even if the enclave itself does not use C++.</li>
</ul></li>
<li>EDL File — Link an EDL file with the enclave project. This is mandatory if you are building an enclave that exposes enclave interfaces, but optional if your library does not include any enclave interfaces.</li>
</ul><p><strong>Signing Key:</strong></p>
<p>Import an existing signing key to the enclave project if you have a private key and want to use it for your enclave. Use the <strong>Browse…</strong> option to navigate to your PEM file and select it. A random key will be generated by Visual Studio if no file is selected. The enclave signing tool will sign the enclave with the key at the end of the build flow unless you are building a Production mode enclave.</p>
<p>If you are building an enclave library, no signing key is needed. Enclave libraries are not signed.</p>
<p><strong>Note:</strong> Use of the Visual Studio generated key for the enclave with the one-step signing process is supported in Debug, Simulation, and Pre-Release modes. You must provide a key and use the two-step signing process if you are creating/building an enclave in Release mode.</p>
<p>6. Click <strong>Finish</strong> when done. The Intel SGX SDK Visual Studio wizard will create the enclave project with the chosen settings.</p>
<h3>Configure the enclave settings</h3>
<p>The <strong>Enclave Settings</strong> dialog window helps you create and maintain the Enclave Configuration File (ECF). The ECF is part of the enclave project and provides the information for the enclave metadata. To configure enclave settings, follow these steps:</p>
<p>1. In Visual Studio, open the solution that contains the enclave project.</p>
<p>2. Right click on the enclave, then select <strong>Intel® SGX Configuration-&gt;Enclave Settings</strong>, as shown in Figure 9. The <strong>Enclave Settings</strong> dialog window opens, as shown in Figure 10, allows you to modify the enclave settings.</p>
<ul><li>The <strong>Enclave Settings</strong> dialog window (organized into <strong>Basic</strong> and <strong>Advanced</strong> screens) allows you to update the enclave settings summarized in Table 1. Accepting the defaults works for most applications during the early stages of development.</li>
<li>The <strong>Advanced Settings</strong> dialog, shown in Figure 11, shows the interface to modify the advanced features. If you have enough Intel SGX knowledge to modify these settings, click the <strong>Advanced…</strong> button.</li>
<li>The <strong>Debug Selection</strong> checkbox should be unchecked, since the build configuration for your project is set to Debug mode. When your application is complete and you change your project build configuration to Release mode, the <strong>Debug Selection</strong> box will be checked to reflect that change.</li>
</ul><table align="center" border="1"><tbody><tr><td style="width:710px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Configure ECF 1" title="Getting Started with Intel SGX SDK for Windows Configure ECF 1" height="677" width="807" src="https://software.intel.com/sites/default/files/managed/7f/92/get-started-sgx-sdk-win-vs-configure-ecf-1.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 9. Opening the Enclave Settings dialog window</strong></p>
<p> </p>
<table align="center" border="1"><tbody><tr><td style="width:734px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Configure ECF 2" title="Getting Started with Intel SGX SDK for Windows Configure ECF 2" height="479" width="814" src="https://software.intel.com/sites/default/files/managed/93/99/get-started-sgx-sdk-win-vs-configure-ecf-2.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 10. Enclave Settings dialog window—Basic Settings</strong></p>
<p><strong>Table 1. Enclave Settings Descriptions</strong></p>
<table border="1" style="width:625px"><thead><tr><th colspan="3" style="width:625px">
<p>Basic</p>
</th>
</tr></thead><tbody><tr><td style="width:213px">
<p><strong>Setting Name</strong></p>
</td>
<td style="width:232px">
<p><strong>Description</strong></p>
</td>
<td style="width:180px">
<p><strong>ECF Tag</strong></p>
</td>
</tr><tr><td style="width:213px">
<p>Product ID</p>
</td>
<td style="width:232px">
<p>ISV assigned Product ID</p>
</td>
<td style="width:180px">
<p>&lt;ProdID&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>ISV SVN</p>
</td>
<td style="width:232px">
<p>ISV assigned SVN</p>
</td>
<td style="width:180px">
<p>&lt;ISVSVN&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Thread Stack Size</p>
</td>
<td style="width:232px">
<p>The stack size per trusted thread (in bytes).</p>
</td>
<td style="width:180px">
<p>&lt;StackMaxSize&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Global Heap Size</p>
</td>
<td style="width:232px">
<p>The heap size for the enclave (in bytes).</p>
</td>
<td style="width:180px">
<p>&lt;HeapSizeMax&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Thread Number</p>
</td>
<td style="width:232px">
<p>The number of trusted threads.</p>
</td>
<td style="width:180px">
<p>&lt;TCSNum&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Thread Bound Policy</p>
</td>
<td style="width:232px">
<p>TCS management policy.</p>
</td>
<td style="width:180px">
<p>&lt;TCSPolicy&gt;</p>
</td>
</tr><tr><td colspan="3" style="width:625px">
<p><strong> Advanced</strong></p>
</td>
</tr><tr><td style="width:213px">
<p><strong>Setting Name</strong></p>
</td>
<td style="width:232px">
<p><strong>Description</strong></p>
</td>
<td style="width:180px">
<p><strong>ECF Tag</strong></p>
</td>
</tr><tr><td style="width:213px">
<p>Disable Debug</p>
</td>
<td style="width:232px">
<p>0 = Enclave can be debugged.</p>
<p>1 = Enclave cannot be debugged</p>
</td>
<td style="width:180px">
<p>&lt;DisableDebug&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Miscellaneous Select</p>
</td>
<td style="width:232px">
<p>Reserved for future use. Must be 0.</p>
</td>
<td style="width:180px">
<p>&lt;MiscSelect&gt;</p>
</td>
</tr><tr><td style="width:213px">
<p>Miscellaneous Mask</p>
</td>
<td style="width:232px">
<p>Reserved for future use. Must be 0xFFFFFFFF.</p>
</td>
<td style="width:180px">
<p>&lt;MiscMask&gt;</p>
</td>
</tr></tbody></table><table align="center" border="1"><tbody><tr><td style="width:625px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Configure ECF 3" title="Getting Started with Intel SGX SDK for Windows Configure ECF 3" height="472" width="674" src="https://software.intel.com/sites/default/files/managed/94/86/get-started-sgx-sdk-win-vs-configure-ecf-3.PNG" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 11. Enclave setting dialog window—advanced settings</strong></p>
<p>The <strong>Misc Select</strong> and <strong>Misc Mask</strong> fields are reserved for future extension. Currently only 0 can be set for Misc Select and 0xFFFFFFFF can be set for <strong>Misc Mask</strong>.</p>
<p><strong>Note: </strong>For efficient memory usage, you may want to adjust the stack and heap memory sizes during the later stages of development, using the Enclave Memory Measurement Tool (EMMT) to help you make decisions. Information on this tool is found here: <a href="https://software.intel.com/sites/default/files/managed/09/37/Enclave-Measurement-Tool-Intel-SGX.pdf">https://software.intel.com/sites/default/files/managed/09/37/Enclave-Measurement-Tool-Intel-SGX.pdf</a>.</p>
<p>3. Click <strong>OK</strong> on the <strong>Advanced Settings</strong> dialog (if you opened that window) and <strong>OK</strong> on the <strong>Basic Settings</strong> dialog window to save any setting changes you may have made.</p>
<h3>Import the EDL</h3>
<p>The Enclave-Definition Language (EDL) file defines the interface between the two (untrusted and trusted) parts of your application. Figure 12 shows the EDL file template, which is divided into a <strong>trusted</strong> and an <strong>untrusted</strong> section. The <strong>trusted</strong> functions are written to the enclave’s <strong>.cpp</strong> file, while the <strong>untrusted</strong> functions must be implemented in the application.</p>
<p>You can get a feel for how to implement your application’s EDL file by examining the SDK code samples. Also, detailed information on the supported data types and usage is provided in: <a href="https://software.intel.com/sites/default/files/managed/b2/b4/Input-Types-and-Boundary-Checking-EDL.pdf">https://software.intel.com/sites/default/files/managed/b2/b4/Input-Types-and-Boundary-Checking-EDL.pdf</a>.</p>
<pre class="brush:cpp;">enclave {
//Include files
//Import other edl files
//Data structure declarations to be used as
//parameters of the function prototypes in edl
trusted {
/* define ECALLs here. */
//Include file if any.
//It will be inserted in the trusted header file (enclave_t.h)
//Trusted function prototypes
};
untrusted {
/* define OCALLs here. */
//Include file if any.
//It will be inserted in the untrusted header file (enclave_u.h)
//Untrusted function prototypes
};</pre>
<p><strong>Figure 12. Enclave-Definition Language file template.</strong></p>
<p>1. To import the EDL file for the enclave into the application in Visual Studio, right click on the <strong>Application Settings</strong>, then navigate to <strong>Intel® SGX Configuration</strong><strong>-&gt;Import Enclave</strong>. The dialog shown in Figure 13 is displayed. Select the checkbox for the EDL file to import and click <strong>Import EDL</strong>.</p>
<table align="center" border="1"><tbody><tr><td style="width:638px">
<p align="center"><span><img alt="Getting Started with Intel SGX SDK for Windows Import EDL" title="Getting Started with Intel SGX SDK for Windows Import EDL" height="789" width="1158" src="https://software.intel.com/sites/default/files/managed/2e/70/get-started-sgx-sdk-import-edl-1.png" /></span></p>
</td>
</tr></tbody></table><p><strong>Figure 13. Importing an Enclave definition (EDL file)</strong></p>
<h3>Building, signing, and debugging the application</h3>
<p>After the EDL file has been imported into the application, you are ready to verify the project build settings and build the application. Follow these steps:</p>
<p>1. Verify the following in Visual Studio:</p>
<ul><li>Make sure that the build configuration is set to <strong>Debug</strong> mode, as shown in Figure 2. (You can change this to <strong>Pre-Release</strong> or <strong>Release</strong> mode near the end of your design cycle.)</li>
<li>Make sure that <strong>Platform Tools</strong> is set to the correct compiler, as shown in Figure 3.</li>
<li>Make sure that <strong>Debugger to launch</strong> is set to <strong>Intel(R) SGX Debugger</strong>, as shown in Figure 4.</li>
<li>Make sure that <strong>Working Directory</strong> is set to <strong>$(OutDir)</strong> for both the enclave and application settings, as shown in Figure 4.</li>
</ul><p>2. Build the solution. Common build errors and suggested resolutions are described later in this article.</p>
<h4>Enclave signing</h4>
<p>Signing an enclave is a process that involves producing a signature structure containing enclave properties such as the enclave measurement. Once an enclave is signed in such a structure, modifications to the enclave file (such as code, data, signature, etc.) can be detected (and blocked by Intel SGX at enclave load time).</p>
<p>For Simulation, Debug, and Pre-Release mode enclaves, you can use the one-step signing process to sign your enclave; this flow uses the private key on the development platform. However, for Production mode enclaves, you must use the two-step signing process because the ISV’s private key will be on a separate signing facility/platform. These two signing processes are summarized below.</p>
<ul><li>One-step signing process—Signing an enclave using a private key available on the build system.</li>
<li>Two-step signing process—Signing an enclave using a private key stored on a secure facility or platform. The overall flow is as follows:
<ul><li>Generate the enclave signing material and take the material to the signing facility/platform.</li>
<li>At the signing facility/platform, sign the file containing the enclave signing material.</li>
<li>Take the resulting signature file (signature.hex) back to the build platform).</li>
<li>On the build platform, sign the enclave using the signature file and public key:</li>
</ul></li>
</ul><p>The Intel SGX SDK includes the <strong>sgx_sign</strong> tool to perform enclave signing. This tool is automatically invoked when building an Intel SGX application in Visual Studio. One-step signing is used for Simulation, Debug, and Pre-Release mode enclaves, while two-step signing is used for Release mode enclaves.</p>
<p>See <a href="https://software.intel.com/sites/default/files/managed/78/4a/overview-signing-whitelisting-intel-sgx-enclaves.pdf">https://software.intel.com/sites/default/files/managed/78/4a/overview-signing-whitelisting-intel-sgx-enclaves.pdf</a> for more information on signing enclaves and whitelisting enclave signers.</p>
<h4>Debugging enclaves</h4>
<p>The topic of debugging enclave code goes beyond the <em>Getting Started</em> phase. For now it's good to understand that the standard Windows Debugger will not work with enclaves; you must use the Intel(R) SGX Debugger for that. An introduction to using the Intel(R) SGX Debugger with enclaves is provided at: <a href="https://software.intel.com/sites/default/files/managed/c8/a1/Debugging-Intel-SGX-Enclaves-in-Windows.pdf">https://software.intel.com/sites/default/files/managed/c8/a1/Debugging-Intel-SGX-Enclaves-in-Windows.pdf</a>.</p>
<p><strong>Note:</strong> Debugger breakpoints inside enclaves do not work in the <em>initial</em> release Windows 10 Anniversary Edition—version 1607. If you are using Windows 10 Anniversary Edition, please update the OS Build to 14393.479 or later. See <a href="https://technet.microsoft.com/en-us/windows/release-info.aspx" rel="nofollow">https://technet.microsoft.com/en-us/windows/release-info.aspx</a> for more details.</p>
<h3>Performance analysis</h3>
<p>Performance analysis of enclave code is typically performed later in the development cycle, usually with Pre-Release code. When your application is ready, you can use the Intel® VTune® Amplifier XE to capture performance information to help you tune your enclave code. An introduction to using Intel VTune is provided at: <a href="https://software.intel.com/sites/default/files/managed/ab/79/Using-VTune-Intel-SGX-Applications-Windows.pdf">https://software.intel.com/sites/default/files/managed/ab/79/Using-VTune-Intel-SGX-Applications-Windows.pdf</a>.</p>
<h3>Errors during application development</h3>
<p>This section contains common errors related to development of Intel SGX applications, along with suggested resolution:</p>
<p>1. <strong>Error: MSB8020: The build tools for Intel C++ Compiler 16.0 (Platform Toolset = ‘Intel C++ Compiler 16.0’) cannot be found.</strong> (<i>actual message shortened</i>). The default C++ compiler cannot be found.</p>
<ul><li><strong>Resolution: </strong>The quickest fix is to select <strong>Visual Studio Compiler</strong> under <strong>Properties-&gt;General-&gt;Platform Toolset</strong> for the project. You can also purchase the Intel C++ 16.0 Compiler and install it.</li>
</ul><p>2. <strong>Error: Enclave file not created:</strong> This error occurs when the project has the <b>Working Directory</b> set to <strong>$(ProjectDir)</strong></p>
<ul><li><strong>Resolution: </strong>Right click <strong>Project-&gt;Properties-&gt;Debugging-&gt;Working Directory</strong> and change <strong><strong>$(ProjectDir)</strong></strong> to <strong><strong>$(OutDir)</strong></strong></li>
</ul><p>3. <strong>Error: Unable to start program:</strong> This error occurs when the application program is not set up as the startup program.</p>
<ul><li><strong>Resolution: </strong>Right click the application and select <b>Set as startup project</b>.</li>
</ul><p>4. <strong>Error: SGX_ERROR_INVALID_METADATA (0X2009):</strong> The metadata embedded within the enclave image is corrupt or missing. The signature, heap size and no. of threads are a part of the metadata of the enclave.</p>
<ul><li><strong>Resolution:</strong> Check and change the corresponding components to valid values.</li>
</ul><p>5. <strong>Error: LNK2019: unresolved external symbol:</strong> This error occurs when any trusted or untrusted library required for a function is not available to the application/enclave. When a trusted/untrusted library is used in an application/enclave it must be linked to the application/enclave or a Linker error is thrown.</p>
<ul><li><strong>Resolution:</strong> Right-click the <strong>Project-&gt;Properties-&gt;Linker-&gt;Input-.Additional Library</strong> dependencies. Select <strong>Edit</strong> from the drop down list and add the required libraries, and click <strong>OK</strong>.</li>
</ul><p>6. <strong>Error: SGX_ERROR_INVALID_VERSION (0x200D):</strong> Metadata version is inconsistent between uRTS (untrusted Run-time System) and sgx_sign or the uRTS is incompatible with the current platform.</p>
<ul><li><strong>Resolution:</strong> Uninstall the current SDK and PSW version and install the version suitable for the platform.</li>
</ul><p>7. <strong>Error: Application Crash:</strong> When there is a power failure or an application is terminated, the enclave gets destroyed.</p>
<ul><li><strong>Resolution: </strong><span>Rebuild the enclave after the termination process is done to resolve the power failure issue. Repeated crashes with no evidence of power failure indicates the need for debugging of an issue.</span></li>
</ul><p>8. <strong>Error: SGX_ERROR_NO_DEVICE (0x2006):</strong> This error is encountered when there is an older version of Intel SGX PSW installed in the system or if the CPU does not support the version of Intel SGX currently installed. The version can be detected using the code provided at: <a href="https://software.intel.com/articles/properly-detecting-intel-software-guard-extensions-in-your-applications">https://software.intel.com/articles/properly-detecting-intel-software-guard-extensions-in-your-applications</a>.</p>
<ul><li><strong>Resolution:</strong> Uninstall the mismatched Intel SGX PSW and install a version supported by the system.</li>
</ul><p>9. <strong>Error: SGX_ERROR_OUT_OF_EPC: </strong>There is not enough EPC memory to load one of the Architecture Enclaves needed to complete Intel SGX service, (attestation, enclave launching, etc.) The numbers of system enclaves and running application enclaves created requires more memory than the allocated memory.<span></span></p>
<p>Intel SGX applications should call <span>sgx_destroy_enclaves ()</span> so the OS can reclaim the protected memory or EPC pages from enclaves that have been removed due to power events. <span>Not destroying an enclave will result in EPC memory leakage that could prevent subsequent enclave from loading.</span></p>
<ul><li><strong>Resolution: </strong>The application can destroy enclaves not in use.<span></span></li>
</ul><p>10. <strong>Error: SGX_ERROR_INVALID_PARAMETER: </strong>At least one of the parameters is invalid.</p>
<ul><li><strong>Resolution:</strong> Check whether the pointers used in the EDL file have been given proper direction attributes and/or are being used properly. Detailed information on the supported data types and usage is provided at: <a href="https://software.intel.com/sites/default/files/managed/b2/b4/Input-Types-and-Boundary-Checking-EDL.pdf">https://software.intel.com/sites/default/files/managed/b2/b4/Input-Types-and-Boundary-Checking-EDL.pdf</a>.</li>
</ul><p>11. <strong>Error: SGX_ERROR_INVALID_MISC:</strong> The Misc Select/Misc Mask settings are not correct.</p>
<ul><li><strong><strong>Resolution:</strong></strong> Set the Misc Select/Misc Mask settings to a supported value.</li>
</ul><p>12. <strong><strong>Error: SGX_ERROR_NDEBUG_ENCLAVE: </strong></strong>The enclave is signed as a product enclave and cannot be created as a debuggable enclave.</p>
<ul><li><strong>Resolution:</strong> Rebuild the enclave as a Debuggable enclave.</li>
</ul><h2><strong><strong>Code snippets</strong></strong></h2>
<h4><strong><strong>Application starting point</strong></strong></h4>
<p>Assume you have the non-Intel SGX enabled application listed below. The program displays the string Hello App! </p>
<pre class="brush:cpp;">#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#define MAX_BUF_LEN 100
void foo(char *buf, size_t len)
{
const char *secret = "Hello App!";
if (len &gt; strlen(secret))
{
memcpy(buf, secret, strlen(secret) + 1);
}
}
int main()
{
char buffer[MAX_BUF_LEN] = "Hello World!";
foo(buffer, MAX_BUF_LEN);
printf("%s", buffer);
return 0;
}</pre>
<p>The snippets that follow show how this same functionality can be divided between an untrusted application and trusted enclave. These snippets include: (1) an EDL file to define the interface between untrusted code and trusted code, (2) enclave code, and (3) application code. When implemented and built correctly, the final application displays the string Hello Enclave!</p>
<h4><strong><strong><span style="color:rgb(83, 86, 90)">EDL snippet</span></strong></strong></h4>
<p>This EDL file content defines the enclave interface, which exposes the trusted interface foo.</p>
<pre class="brush:cpp;">// sample_enclave.edl
enclave {
trusted {
public void foo([out, size=len] char* buf, size_t len);
};
};</pre>
<h4><strong><strong><strong>Enclave Code</strong></strong></strong></h4>
<pre class="brush:cpp;">// sample_enclave.cpp
#include "sample_enclave_t.h"
#include &lt;string.h&gt;
void foo(char *buf, size_t len)
{
const char *secret = "Hello Enclave!";
if (len &gt; strlen(secret))
{
memcpy(buf, secret, strlen(secret) + 1);
}
}</pre>
<h4><strong><strong><strong>Application Code</strong></strong></strong></h4>
<pre class="brush:cpp;">#include &lt;stdio.h&gt;
#include &lt;tchar.h&gt;
#include "sgx_urts.h"
#include "sample_enclave_u.h"
#define ENCLAVE_FILE _T("sample_enclave.signed.dll")
#define MAX_BUF_LEN 100
int main()<strong>
</strong>{
sgx_enclave_id_t eid;
sgx_status_t ret = SGX_SUCCESS;
sgx_launch_token_t token = {0};
int updated = 0;
char buffer[MAX_BUF_LEN] = "Hello World!";
// Create the Enclave with above launch token.
ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &amp;token, &amp;updated, &amp;eid, NULL);
if (ret != SGX_SUCCESS) {
printf("App: error %#x, failed to create enclave.\n", ret);
return -1;
}
// An Enclave call (ECALL) will happen here.
foo(eid, buffer, MAX_BUF_LEN);
printf("%s", buffer);
// Destroy the enclave when all Enclave calls finished.
if(SGX_SUCCESS != sgx_destroy_enclave(eid))
return -1;
return 0;
}</pre>
<h2><strong><strong>Training and Documentation</strong></strong></h2>
<table align="left"><thead><tr><th><span>Document</span></th>
<th><span>Description</span></th>
</tr></thead><tbody><tr><td><a href="https://software.intel.com/sgx-sdk/documentation">Release Notes</a></td>
<td>
<p>The Release Notes document contains the most up-to-date information about the product, including:</p>
<ul><li>Overview</li>
<li>What's New</li>
<li>System Requirements</li>
<li>Installation Notes</li>
<li>Known Issues and Limitations</li>
</ul></td>
</tr><tr><td><a href="https://software.intel.com/sgx-sdk/documentation">Installation Guide</a></td>
<td>The Installation Guide contains information on obtaining, installing, and uninstalling Intel® Software Guard Extensions on Windows* OS.</td>
</tr><tr><td><a href="https://software.intel.com/sgx-sdk/documentation">Developer Guide</a></td>
<td>The Developer Guide provides guidance on how to develop robust application enclaves based on Intel® Software Guard Extensions technology.</td>
</tr><tr><td><a href="https://software.intel.com/sgx-sdk/documentation">Developer Reference</a></td>
<td>The Developer Reference covers tutorials, tools, API reference as well as sample code.</td>
</tr><tr><td>Online Resources</td>
<td>
<ul><li><a href="https://software.intel.com/sgx">Product web site</a></li>
<li><a href="https://software.intel.com/sgx/code-samples">Samples and tutorials portal</a></li>
<li><a href="https://software.intel.com/sgx/resource-library">Whitepapers, articles, and more</a></li>
<li><a href="https://software.intel.com/forums/intel-software-guard-extensions-intel-sgx">Intel SGX Forums</a></li>
<li><a href="https://software.intel.com/intel-software-technical-documentation">Intel Software Documentation Library</a></li>
</ul></td>
</tr></tbody></table>Wed, 21 Jun 2017 16:48:01 -0700admin737361Use Intel SGX Templates for the GNU* Autoconf* Build Systemhttps://software.intel.com/en-us/articles/intel-sgx-templates-for-the-gnu-autoconf-build-system
<h4> </h4>
<blockquote>
<p>This project is now being <a href="https://github.com/intel/sgx-autotools-templates" rel="nofollow">hosted on GitHub</a>.</p>
</blockquote>
<p><a href="http://www.gnu.org/software/autoconf/autoconf.html" target="_blank" rel="nofollow">GNU* Autoconf*</a> is a popular build system that sees extensive use for Linux* source code packages. It produces a consistent, easy-to-use, and well-understood configuration script that allows end users and systems integrators to tailor software packages for their installation environments, almost always without any manual intervention. To create a configure script, the software developer creates a template file consisting of a series of macros that define the software package configuration needs, and then processes it with the Autoconf utility. GNU Autoconf provides convenient automation and standardization for common, and often tedious, tasks such as building Makefiles and configurable header files.</p>
<p>One of the key features of the Autoconf system is that it is extensible. Software developers can create macros that expand its functionality in order to support customized build and configuration needs. In this article, we introduce a set of macros and Makefile templates that do exactly this: Extend the functionality of Autoconf to simplify the process of building software that makes use of <a href="https://software.intel.com/en-us/sgx">Intel® Software Guard Extensions (Intel® SGX)</a>. The templates themselves, along with a sample application source tree that makes use of them, are provided as a download.</p>
<h2>Overview</h2>
<p>The Intel SGX templates for the GNU Autoconf package contain four files:</p>
<ul><li>README</li>
<li>aclocal.m4</li>
<li>sgx-app.mk.in</li>
<li>sgx-enclave.mk.in</li>
</ul><h2>README</h2>
<p>The README file has detailed information on the Autoconf macros and Makefile rules and variables that make up the templates. It is a reference document, while this article functions more as a “how to” guide.</p>
<h3>aclocal.m4</h3>
<p>This is where the macros for extending Autoconf are defined. This file can be used as-is, appended to an existing aclocal.m4, or renamed for integration with GNU Automake*.</p>
<h4>sgx-app.mk.in</h4>
<p>This file builds to “sgx-app.mk” and contains Makefile rules and definitions for building Intel SGX applications. It is intended to be included (via an “include” directive) from the Makefile(s) that produce an executable object that includes one or more Intel SGX enclaves.</p>
<h4>sgx-enclave.mk.in</h4>
<p>This file builds to “sgx-enclave.mk” and contains Makefile rules and definitions for building Intel SGX enclaves. It must be included (via an “include” directive) from Makefiles that produce an Intel SGX enclave object (*.signed.so file in Linux).</p>
<p>Because this file contains build targets, you should place the include directive <em>after</em> the default build target in the enclave’s Makefile.in.</p>
<h2>Creating configure.ac</h2>
<p>Start by including the macro <code>SGX_INIT</code> in your configure.ac. This macro is required in order to set up the build system for Intel SGX, and it does the following:</p>
<ul><li>Adds several options to the final configure script that let the user control aspects of the build.</li>
<li>Attempts to discover the location of the Intel SGX SDK.</li>
<li>Creates sgx_app.mk from sgx_app.mk.in.</li>
</ul><p><code>SGX_INIT</code> also defines a number of Makefile substitution variables. The ones most likely to be needed by external Makefiles are:</p>
<table class="no-alternate"><tbody><tr><td><strong><code>enclave_libdir</code></strong></td>
<td>Installation path for enclave libraries/objects. Defaults to $EPREFIX/lib.</td>
</tr><tr><td><strong><code>SGX_URTS_LIB</code></strong></td>
<td>The untrusted runtime library name. When the project is built in simulation mode it automatically includes the _sim suffix.</td>
</tr><tr><td><strong><code>SGX_UAE_SERVICE_LIB</code></strong></td>
<td>The untrusted AE service library name. When the project is built in simulation mode it automatically includes the _sim suffix.</td>
</tr><tr><td><strong><code>SGXSDK</code></strong></td>
<td>The location of the Intel® SGX SDK.</td>
</tr><tr><td><strong><code>SGXSDK_BINDIR</code></strong></td>
<td>The directory containing Intel SGX SDK utilities.</td>
</tr><tr><td><strong><code>SGXSDK_INCDIR</code></strong></td>
<td>The location of Intel SGX SDK header files.</td>
</tr><tr><td><strong><code>SGXSDK_LIBDIR</code></strong></td>
<td>The directory containing the Intel SGX SDK libraries needed during linking.</td>
</tr></tbody></table><p>The <code>SGX_INIT</code> macro does not take any arguments.</p>
<pre class="brush:plain;">AC_INIT(sgxautosample, 1.0, john.p.mechalas@intel.com)
AC_PROG_CC()
AC_PROG_CXX()
AC_PROG_INSTALL()
AC_CONFIG_HEADERS([config.h])
SGX_INIT()
AC_CONFIG_FILES([Makefile])
AC_OUTPUT()
</pre>
<p>Next, define the enclaves. Each enclave is expected to have a unique name, and should be located in a subdirectory that is named after it. Specify the enclaves using the <code>SGX_ADD_ENCLAVES</code> macro. It takes one or two arguments:</p>
<ol><li>(required) The list of enclave names.</li>
<li>(optional) The parent directory where the enclave subdirectories can be found. This defaults to “.”, the current working directory, if omitted.</li>
</ol><p>Note that you can invoke this macro multiple times if your project has multiple enclaves and they do not share a common parent directory. Enclave names should not include spaces or slashes.</p>
<pre class="brush:plain;">AC_INIT(sgxautosample, 1.0, john.p.mechalas@intel.com)
AC_PROG_CC()
AC_PROG_CXX()
AC_PROG_INSTALL()
AC_CONFIG_HEADERS([config.h])
SGX_INIT()
# Add enclave named “EnclaveHash” in the EnclaveHash/ directory
SGX_ADD_ENCLAVES([EnclaveHash])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT()
</pre>
<p>In addition to defining the enclaves, this macro does the following:</p>
<ul><li>Builds sgx_enclave.mk from sgx_enclave.mk.in.</li>
<li>Builds the Makefiles in each enclave subdirectory from their respective Makefile.in sources.</li>
</ul><h2>Enclave Makefiles</h2>
<p>Each enclave’s Makefile needs to include the global sgx_enclave.mk rules file in order to inherit the rules, targets, and variables that automate enclave builds. Each Enclave must abide by the following rules:</p>
<ul><li>The enclave must be in its own subdirectory.</li>
<li>The name of the subdirectory must match the name of the enclave (for example, an enclave named EnclaveCrypto must be placed in a subdirectory named EnclaveCrypto).</li>
<li>The EDL file for the enclave must also match the enclave name (for example, EnclaveCrypto.edl).</li>
<li>The Makefile must define the name of the enclave in a variable named ENCLAVE (for example, <code>ENCLAVE=EnclaveCrypto</code>).</li>
</ul><p>The sgx_enclave.mk file defines a number of variables for you to use in the enclave’s Makefile:</p>
<table class="no-alternate"><tbody><tr><td><strong><code>ENCLAVE_CLEAN</code></strong></td>
<td>A list of files that should be removed during 'make clean'.</td>
</tr><tr><td><strong><code>ENCLAVE_CPPFLAGS</code></strong></td>
<td>C preprocessor flags.</td>
</tr><tr><td><strong><code>ENCLAVE_CXXFLAGS</code></strong></td>
<td>C++ compiler flags necessary for building an enclave.</td>
</tr><tr><td><strong><code>ENCLAVE_DISTCLEAN</code></strong></td>
<td>A list of files that should be removed during 'make distclean'.</td>
</tr><tr><td><strong><code>ENCLAVE_LDFLAGS</code></strong></td>
<td>Linker flags for generating the enclave .so.</td>
</tr><tr><td><strong><code>ENCLAVE_TOBJ</code></strong></td>
<td>The trusted object file <code>$(ENCLAVE)_t.o</code> that is auto-generated by the sgx_edger8r tool. Include this in your enclave link line and the enclave build dependencies.</td>
</tr></tbody></table><p>Here’s the Makefile.in for the enclave in the sample application included with the templates:</p>
<pre class="brush:plain;">CC=@CC@
CFLAGS=@CFLAGS@
CPPFLAGS=@CPPFLAGS@
LDFLAGS=@LDFLAGS@
INSTALL=@INSTALL@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
enclave_libdir=@enclave_libdir@
ENCLAVE=EnclaveHash
OBJS=$(ENCLAVE).o
%.o: %.c
$(CC) $(CPPFLAGS) $(ENCLAVE_CPPFLAGS) $(CFLAGS) $(ENCLAVE_CFLAGS) -c $&lt;
all: $(ENCLAVE).so
install: all
$(INSTALL) -d $(enclave_libdir)
$(INSTALL) -t $(enclave_libdir) $(ENCLAVE_SIGNED)
include ../sgx_enclave.mk
$(ENCLAVE).so: $(ENCLAVE_TOBJ) $(OBJS)
$(CC) $(CFLAGS) -o $@ $(ENCLAVE_TOBJ) $(OBJS) $(LDFLAGS) $(ENCLAVE_LDFLAGS)
clean:
rm -f $(OBJS) $(ENCLAVE_CLEAN)
distclean: clean
rm -f Makefile $(ENCLAVE_DISTCLEAN)
</pre>
<h2>Application Makefiles</h2>
<p>Application components that reference enclaves need to include sgx_app.mk in their Makefile. It defines a number of rules, targets, and variables to assist with the build.</p>
<p>To get a list of all the enclaves in the project, the Makefile must define a list variable from the <code>@SGX_ENCLAVES@</code> substitution variable that is set by Autoconf:</p>
<p><code>SGX_ENCLAVES:=@SGX_ENCLAVES@</code></p>
<p>This should be included as a build target as well, to ensure that all enclaves are built along with the application.</p>
<p><code>all: enclavetest $(SGX_ENCLAVES)</code></p>
<p>The variables most likely to be needed by the application’s Makefile are:</p>
<table class="no-alternate"><tbody><tr><td><strong><code>ENCLAVE_CLEAN</code></strong></td>
<td>A list of files that should be removed during 'make clean'.</td>
</tr><tr><td><strong><code>ENCLAVE_UOBJS</code></strong></td>
<td>The untrusted object files <code>$(ENCLAVE)_u.o</code> that are auto-generated by the sgx_edger8r tool. Include these in your application link line and the enclave build dependencies.</td>
</tr><tr><td><strong><code>ENCLAVE_UDEPS</code></strong></td>
<td>The untrusted source and header files that are auto-generated by the sgx_edger8r tool. Include these in your compilation dependencies when building your application.</td>
</tr></tbody></table><p>Here’s the Makefile for the sample application that is bundled with the templates:</p>
<pre class="brush:plain;">SGX_ENCLAVES:=@SGX_ENCLAVES@
CC=@CC@
CFLAGS=@CFLAGS@ -fno-builtin-memsetqq
CPPFLAGS=@CPPFLAGS@
LDFLAGS=@LDFLAGS@ -L$(SGXSDK_LIBDIR)
LIBS=@LIBS@
INSTALL=@INSTALL@
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
libdir=@libdir@
enclave_libdir=@enclave_libdir@
APP_OBJS=main.o
%.o: %.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) -I$(SGXSDK_INCDIR) $&lt;
all: enclavetest $(SGX_ENCLAVES)
install: install-program install-enclaves
install-program: all
$(INSTALL) -d $(bindir)
$(INSTALL) -t $(bindir) enclavetest
install-enclaves:
for dir in $(SGX_ENCLAVES); do \
$(MAKE) -C $$dir install; \
done
include sgx_app.mk
enclavetest: $(ENCLAVE_UOBJS) $(APP_OBJS)
$(CC) -o $@ $(LDFLAGS) $(APP_OBJS) $(ENCLAVE_UOBJS) $(LIBS) -l$(SGX_URTS_LIB)
clean: clean_enclaves
rm -f enclavetest $(APP_OBJS) $(ENCLAVE_CLEAN)
distclean: clean distclean_enclaves
rm -rf Makefile config.log config.status config.h autom4te.cache
rm -rf sgx_app.mk sgx_enclave.mk
</pre>
<p>Note that the link line for the application references the sgx_urts library via the Makefile variable <code>$(SGX_URTS_LIB)</code>. This is to support builds made in simulation mode: The variable will automatically append the _sim suffix to the library names so that the Makefile doesn’t have to define multiple build targets. <em>Always use the variables </em><em><code>$(SGX_URTS_LIB)</code></em><em> and </em><em><code>$(SGX_UAE_SERVICE_LIB)</code></em><em> in your Makefile instead of the actual library names.</em></p>
<h2>Running the Configure Script</h2>
<p>When the configure.ac file is processed by Autoconf, the resulting configure script will have some additional command-line options. These are added by the <code>SGX_INIT</code> macro:</p>
<p><code>--enable-sgx-simulation </code></p>
<p>Build the project in simulation mode. This is for running and testing Intel SGX applications on hardware that does not support Intel SGX instructions.</p>
<p><code>--with-enclave-libdir-path=path</code></p>
<p>Specify where enclave libraries should be installed, and set the <code>enclave_libdir</code> substitution variable in Makefiles. The default is <code>$EPREFIX/lib</code>.</p>
<p><code>--with-sgx-build=debug|prerelease|release</code></p>
<p>Specify whether to build the Intel SGX application in debug, prerelease, or release mode. The default is to build in debug mode.</p>
<p>See the Intel SGX SDK for information on the various build modes. Note that you cannot mix release or prerelease modes with the <code>--enable-sgx-simulation</code> option.</p>
<p><code>--with-sgxsdk=path</code></p>
<p>Specify the Intel SGX SDK installation directory. This overrides the auto-detection procedure.</p>
<h2>Summary and Future Work</h2>
<p>These templates simplify the process of integrating the GNU build system with Intel SGX projects. They eliminate tedious, redundant coding, relieve the developer of the burden of remembering and entering the numerous libraries and compiler and linker flags needed to build Intel SGX enclaves, and automate the execution of supporting tools such as sgx_edger8r and sgx_sign.</p>
<p>While this automation and integration is valuable, there is still a non-trivial amount of effort required to set up the project environment. Further automation might be possible through the use of GNU Automake, which is designed to generate the Makefile templates that are in turn processed by Autoconf.</p>
<p>The build environment for Intel SGX applications can be complicated. Integration with build systems such as GNU Autoconfig, and potentially Automake, can save the developer considerable time and make their projects less prone to errors.</p>
Tue, 09 May 2017 09:24:41 -0700John M. (Intel)733763Intel® SGX and Side-Channelshttps://software.intel.com/en-us/articles/intel-sgx-and-side-channels
<p>Since launching Intel® Software Guard Extensions (Intel® SGX) on 6th Generation Intel® Core™ processors in 2015, there have been a number of academic articles looking at various usage models and the security of Intel SGX. Some of these papers focus on a class of attack known as a side-channel attack, where the attacker relies on the use of a shared resource to discover information about processing occurring in some other privileged domain that it does not have direct access to.</p>
<p>In general, these research papers do not demonstrate anything new or unexpected about the Intel SGX architecture. Preventing side channel attacks is a matter for the enclave developer. Intel makes this clear In the security objectives for Intel SGX, which we published as part of our workshop tutorial at the International Symposium on Computer Architecture in 2015, the slides for which can be found here <a href="/sites/default/files/332680-001.pdf" rel="nofollow">[slides 109-121]</a>, and in the <a href="m/en-us/sgx-sdk/documentation" rel="nofollow">Intel® SGX SDK Developer's Manual</a>.</p>
<p>This is not to say that Intel does not care about side-channel attacks.</p>
<p>Intel has a strong collaboration with security experts in both academia and the industry and values their ability to both identify the next generation of threats as well as solutions. The authors of many of the papers highlighting potential attacks have presented their work at Intel allowing for a robust dialog on implications and solutions. When these types of vulnerabilities have been found, Intel has worked with its own developers, Independent Software Vendors (ISVs) and open source partners to address the vulnerabilities. For instance, the type of side-channel attack identified on the RSA implementation used in one of the academic papers was well-known for some time and is addressed by other software solutions like the OpenSSL* crypto library.</p>
<p>For information about the side-channel security issue, please refer to our <a href="/en-us/side-channel-security-support" rel="nofollow">support page</a>.</p>
Thu, 16 Mar 2017 23:31:27 -0700Simon Johnson (Intel)720907Intel® Software Guard Extensions Tutorial Series: Part 8, GUI Integrationhttps://software.intel.com/en-us/articles/intel-sgx-tutorial-series-part-8-gui-integration
<p><a class="button-cta" href="/protected-download/676750/713868" rel="nofollow">Download ZIP</a> [573 KB]</p>
<p><a class="button-cta" href="/sites/default/files/managed/6f/22/Part-8-GUI-Integration.pdf" rel="nofollow">Download PDF</a> [919.5 KB]</p>
<p>Part 8 of the <a href="/en-us/sgx" rel="nofollow">Intel® Software Guard Extensions (Intel® SGX)</a> tutorial series integrates the graphical user interface (GUI) with the back end. In this part, we’ll examine the implications of mixing managed code with enclaves and the potential for undermining the security that is gained from Intel SGX. We’ll scope out the risks to our secrets and then develop mitigation strategies to limit their exposure.</p>
<p>You can find a list of all of the published tutorials in the article <a href="/en-us/articles/introducing-the-intel-software-guard-extensions-tutorial-series" rel="nofollow">Introducing the Intel® Software Guard Extensions Tutorial Series</a>.</p>
<p>Source code is provided with this installment of the series.</p>
<h2>The User Interface</h2>
<p>When we developed our application requirements back in <a href="/en-us/articles/intel-software-guard-extensions-tutorial-part-2-app-design" rel="nofollow">Part 2 of the tutorial series</a>, we made a decision to use the Microsoft* .NET Framework* to develop the user interface. That decision was based on the need to limit the complexity of the application development as well as limit dependencies on external software libraries.</p>
<p>The main window for the UI is shown in<a href="#_Ref474931785" rel="nofollow"> Figure 1</a>. It is based on the Windows Presentation Foundation* (WPF), and makes use of standard WPF controls.<a name="_Ref474931785" id="_Ref474931785"> </a></p>
<p><span><a class="bigphoto" href="https://software.intel.com/sites/default/files/managed/19/01/sgx-tutorial-series-part-8-fig1-large.png"><img alt="Figure 1" title="Figure 1" src="https://software.intel.com/sites/default/files/managed/7c/59/sgx-tutorial-series-part-8-fig1-small.png" /><img class="bigphoto-magnifier" src="https://software.intel.com/sites/all/modules/custom/intel_wysiwyg/images/magnifier.png" alt="" /></a></span></p>
<p><strong>Figure 1.</strong> <em>The Tutorial Password Manager user interface (click to enlarge).</em></p>
<p>This decision came at a cost, however. .NET applications execute under the supervision of the Common Language Runtime, and the CLR includes a memory manager with garbage collection.</p>
<h2>The Problem</h2>
<p>In a traditional application—one built on a native code base—the developer is responsible for allocating memory as it’s needed, and must keep track of the addresses of allocated memory so that it can be freed when it’s no longer needed. Failing to free memory that has been allocated leads to memory leaks, which in turn causes the application to consume more and more memory over time. In a high-performance application, the developer may even need to consider how the variables and objects in their application are <em>arranged</em> in memory, because some hardware instructions are sensitive to byte boundaries, and some algorithms depend on efficient use of the CPU cache.</p>
<p>In a managed application, however, the developer is abstracted from these details. The developer doesn’t allocate memory directly when an object is created, and that memory doesn’t have to be explicitly freed by the developer when it’s no longer needed. The runtime keeps track of the number of references to an object, and when the reference count drops to zero it is flagged for cleanup at a later time by a subsystem known as the garbage collector. The garbage collector has several jobs, but its primary ones are freeing up unused memory and compacting allocated memory into contiguous blocks for efficient usage.</p>
<p>Memory managed applications have a number of advantages, and the biggest of these is that they eliminate entire categories of software bugs. Unfortunately, they also have a very big <em>disadvantage</em> when it comes to application security: the developer is no longer in control over the low-level memory management, which means there is no way to guarantee that sensitive areas of memory can be securely erased or overwritten. The garbage collector can, at any time during a program’s execution, manipulate all the memory under its control. It can move objects around, make copies of them, delay writes to memory until they are needed, and even eliminate writes that it deems unnecessary. For a security application that needs to guarantee that a region of memory is erased or overwritten, memory managed environments are bad news.</p>
<h2>How Big is the Problem, Really?</h2>
<p>We can scope the extent of the problem by looking at the <strong>String</strong> class in .NET. Nearly every UI widget that displays text output to the screen in .NET does so through a <strong>String</strong>, and we can use that to assess just how big of a security problem we are creating if we put sensitive information into a UI control. To do that, we’ll write a simple Windows Forms* application that merely updates a text box, empties it, and then resets it.</p>
<p><a href="#_Ref473641397" rel="nofollow">Figure 2</a> shows the test application window, and <a href="#_Ref473641403" rel="nofollow">Figure 3</a> shows the relevant code that modifies the string in the <strong>TextBox</strong> control.<a name="_Ref473641397" id="_Ref473641397"> </a></p>
<p><img alt="Figure 2" src="https://software.intel.com/sites/default/files/managed/ec/c2/sgx-tutorial-series-part-8-fig2.png" title="Figure 2" /></p>
<p><strong>Figure 2</strong>. <em>The String Demo application window.</em><a name="_Ref473641403" id="_Ref473641403"> </a></p>
<pre class="brush:csharp;">private void button2_Click(object sender, EventArgs e)
{
textBox1.Text = "furniture";
textBox1.Text = "compound";
textBox1.Text += "-complex";
textBox1.Clear();
textBox1.Text = "Click 'Run' to go again";
}
</pre>
<p><strong>Figure 3. </strong><em>String operations on the TextBox control.</em></p>
<p>We’ll compile this application in Release mode, execute it, and then attach to it using the Windows Debugger*, WinDbg, which is part of the Debugging Tools for Windows* from Microsoft. One of the features of WinDbg is that you can load other DLLs to extend its functionality, and the SOS.DLL from the .NET Framework exposes a command to dump classes of a specified type from the memory heap (for more information on this topic, see the article <a href="https://www.codeproject.com/Articles/42766/NET-Debugging-Dump-All-Strings-from-a-Managed-Code" target="_blank" rel="nofollow">.NET Debugging: Dump All Strings from a Managed Code Process</a> at CodeProject*).</p>
<p>When we dump the <strong>String</strong> objects in the heap right at the start of the application, before clicking the “Run” button, we see all the Strings currently in use by the application. There are a <em>lot</em> of <strong>Strings</strong> on the heap, but the most relevant ones are highlighted in <a href="#_Ref473641617" rel="nofollow">Figure 4</a>.<a name="_Ref473641617" id="_Ref473641617"> </a></p>
<p><img alt="Figure 4" src="https://software.intel.com/sites/default/files/managed/4b/3a/sgx-tutorial-series-part-8-fig4.png" title="Figure 4" /></p>
<p><strong>Figure 4.</strong> <em>Strings in the String Demo application. Highlighted strings correspond to the user interface controls.</em></p>
<p>Here we can see the names of our Windows Form widgets, and the starting text for the <strong>TextBox</strong> widget, “Click ‘Run’ to start”. If we scroll down toward the bottom, we see “String Demo”, the name of our main form, repeated a few dozen times as shown in <a href="#_Ref473641624" rel="nofollow">Figure 5</a>.<a name="_Ref473641624" id="_Ref473641624"> </a></p>
<p><img alt="Figure 5" src="https://software.intel.com/sites/default/files/managed/45/3a/sgx-tutorial-series-part-8-fig5.png" title="Figure 5" /></p>
<p><strong>Figure 5.</strong><em> Duplicates of the same string in the String Demo application.</em></p>
<p>Now, we resume the program and click the “Run” button. This cycles through the operations shown in <a href="#_Ref473641403" rel="nofollow">Figure 3</a>, which returns almost instantly. Returning to WinDbg, we dump the <strong>String</strong> objects once again, and get the output shown in <a href="#_Ref473641653" rel="nofollow">Figure 6</a>.<a name="_Ref473641653" id="_Ref473641653"> </a></p>
<p><img alt="Figure 6" src="https://software.intel.com/sites/default/files/managed/68/f6/sgx-tutorial-series-part-8-fig6.png" title="Figure 6" /></p>
<p><strong>Figure 6.</strong> <em>Strings in the String Demo application, post execution.</em></p>
<p>Note that this <strong>String </strong>dump is from a <em>single execution</em> of the<code> button2_Click()</code>event handler, and the debugger wasn’t attached until a full minute <em>after </em>the execution had completed. This means that, one minute after running through a command sequence in which the execution:</p>
<ol><li>overwrote the textbox <strong>String </strong>with the word “furniture”</li>
<li>immediately overwrote it again, this time with the word “compound”</li>
<li>appended the text “-complex”</li>
<li>cleared the textbox by calling the <code>Clear()</code> method</li>
<li>reset the text to the phrase “Click ‘Run’ to restart”</li>
</ol><p>the memory heap for the application contained <em>multiple</em> <strong>Strings </strong>with the contents “furniture”, “compound”, and “compound-complex”. Clearly, any controls that depend on the <strong>String </strong>class are going to be leaking our secrets, and doing so to multiple places in memory!</p>
<h2>Mitigation and Solution</h2>
<p>Fortunately, most managed code frameworks provide classes that are specifically designed to store sensitive data. These usually work by placing their contents in unmanaged memory, outside of the control of the garbage collector. In the .NET Framework this capability is provided by the <strong>SecureString </strong>class, but we are hamstrung by having only one WPF control that can work with the <strong>SecureString </strong>class out of the box, the <strong>PasswordBox</strong>.</p>
<p>This may not seem like a significant issue since our application’s secrets include passwords, and the <strong>PasswordBox </strong>control is designed specifically for password entry. For most applications this is sufficient, but our application is a password manager, and it must be able to reveal the password to the user on demand. In the Universal Windows Platform* runtime, the <strong>PasswordBox </strong>class provides a property named PasswordRevealMode, which can be set to either “Hidden”, “Visible”, or “Peek” (this last value reveals the password while the user is pressing the “reveal” button on the control.</p>
<p><img alt="Figure 7" src="https://software.intel.com/sites/default/files/managed/1e/6b/sgx-tutorial-series-part-8-fig7.png" title="Figure 7" /></p>
<p><strong>Figure 7.</strong> <em>The Universal Windows Platform version of the PasswordBox control supports a “peek” capability that the WPF control in .NET does not support.</em></p>
<p>The .NET Framework version of the <strong>PasswordBox </strong>control does not have this property, however, which means that the <strong>PasswordBox </strong>control is effectively write-only (from the user’s perspective). <strong>PasswordBox </strong>is fine for <em>entering</em> a password, but it’s not a solution for <em>revealing</em> a password when the user asks to view it. We need to create our own solution.</p>
<h3>Requirements and Constraints</h3>
<p>In <a href="/en-us/articles/software-guard-extensions-tutorial-series-part-3" rel="nofollow">Part 3</a> of the series, we identified two secrets that exit the enclave in clear text so that they can be displayed via the user interface:</p>
<ul><li>The login information for an account (a name for the account, a login or user name, and URL associated with the account).</li>
<li>The account password.</li>
</ul><p>While the login information for a user’s account is sensitive data, accidental exposure does not carry tremendous risk. The entire application <em>could</em> be re-written to make use of native windows, but that would be a huge investment for arguably little gain. A future release of the .NET Framework may contain the functionality that we need in the <strong>PasswordBox </strong>control, so we can accept the risk today and look for the problem to be fixed for us in the future. If later we decide the risk is too great, we could always revisit the decision and implement a native solution in a later release.</p>
<p>For account passwords, however, the day of reckoning has arrived. <em>There is no scenario where it is appropriate to expose a password to the <strong>String</strong> class in .NET.</em> As a password manager, we need the ability to show passwords to the user, but we must not use the .NET Framework to do it.</p>
<h3>The Solution</h3>
<p>We must use a native window when revealing a password to the end user. With a native window we are placing the password in unmanaged memory, and because it’s unmanaged memory we can guarantee that the password is securely erased by making a call to <code>SecureZeroMemory()</code>. The problem with a native window, though, is the same one that drove our design to .NET and WPF in the first place: the default tools for building native windows either force you to build the entire window and messaging handlers from the ground up using the Win32 API, or rely on the large and complex Microsoft Foundation Classes*, which is extremely heavy-handed for our simple application.</p>
<p>To solve this problem we’re going to take a shortcut. Though the Win32 API does not provide convenience methods for building generic windows, it does provide one function for displaying a very simple, modestly configurable dialog box that meets our needs: <code>MessageBox()</code>. The <code>MessageBox()</code> function lets you specify a window title, some caption text, and a button configuration from a number of preset options. It takes care of the window formatting and the event handlers, and it returns an integer value that tells us which button the user clicked.</p>
<p><a href="#_Ref473717812" rel="nofollow">Figure 8</a> shows the dialog box created by our password manager application using this approach. To implement it, we added a method called <code>accounts_view_password()</code> to the <strong>PasswordManagerCoreNative </strong>class. The code listing is given in <a href="#_Ref473717866" rel="nofollow">Figure 9</a>.<a name="_Ref473717812" id="_Ref473717812"> </a></p>
<p><img alt="Figure 8" src="https://software.intel.com/sites/default/files/managed/0a/a6/sgx-tutorial-series-part-8-fig8.png" title="Figure 8" /></p>
<p><strong>Figure 8.</strong> <em>The "view password" window generated by <code>accounts_view_password()</code>.</em><a name="_Ref473717866" id="_Ref473717866"> </a></p>
<pre class="brush:csharp;">int PasswordManagerCoreNative::accounts_view_password(UINT32 idx, HWND hWnd)
{
int rv = NL_STATUS_UNKNOWN;
LPWCH wpass;
UINT16 wlen;
static const wchar_t empty[] = L"(no password stored)";
// First get the password
rv = this-&gt;accounts_get_password(idx, &amp;wpass, &amp;wlen);
if (rv != NL_STATUS_OK) return rv;
// Display our MessageBox
MessageBox(hWnd, (wlen&gt;1) ? wpass : empty, L"Password", MB_OK);
this-&gt;accounts_release_password(wpass, wlen);
return rv;
}</pre>
<p><strong>Figure 9.</strong> <em>The <code>accounts_view_password()</code> method in PasswordManagerCoreNative.</em></p>
<p>The first argument is the index of the account in our vault whose password we want to view. Internally, it makes a call to <code>accounts_get_password()</code> to fetch that password from the vault, and then it calls <code>MessageBox()</code> to display it (with logic to display a canned message if the password string is empty) with a single OK button. Then we free up the password and return.</p>
<p>The second argument to this function is the handle of the owner window. In native code, that handle is a type <strong>HWND</strong>, but our owner window originates from managed code. Getting this handle is a two-step procedure. <strong>PasswordManagerCore </strong>can marshal an <strong>IntPtr </strong>to a native pointer that <code>accounts_get_password()</code> can use, and this is shown in <a href="#_Ref473718822" rel="nofollow">Figure 10</a>, but the <strong>IntPtr </strong>that refers to the owning WPF window has to come from the UI layer of the application.<a name="_Ref473718822" id="_Ref473718822"> </a></p>
<pre class="brush:csharp;">int PasswordManagerCore::accounts_view_password(UInt32 idx, IntPtr hptr)
{
int rv;
UINT32 index = idx;
HWND hWnd = static_cast&lt;HWND&gt;(hptr.ToPointer());
rv = _nlink-&gt;accounts_view_password(index, hWnd);
if (rv != NL_STATUS_OK) return rv;
return rv;
}
</pre>
<p><strong>Figure 10.</strong> <em>The <code>accounts_view_password()</code> method in PasswordManagerCore.</em></p>
<p><a href="#_Ref473718758" rel="nofollow">Figure 11</a> shows the code from EditDialog.xaml.cs. Here, we get a managed handle to the current window and use the <strong>WindowInteropHelper </strong>class from WPF to produce an <strong>IntPtr</strong>.<a name="_Ref473718758" id="_Ref473718758"> </a></p>
<pre class="brush:csharp;"> private void btnView_Click(object sender, RoutedEventArgs e)
{
WindowInteropHelper wih;
Window wnd;
IntPtr hptr;
int rv = 0;
wnd = Window.GetWindow(this);
wih = new WindowInteropHelper(wnd);
hptr = wih.Handle;
rv = mgr.accounts_view_password(pNewItem.index, hptr);
if (rv != PasswordManagerStatus.OK)
{
MessageBox.Show("Couldn't view password: " + MainWindow.returnErrorcode(rv));
return;
}
}</pre>
<p><strong>Figure 11.</strong> <em>The event handler for viewing a password.</em></p>
<p>Viewing the password isn’t the only place where this is needed. Our Tutorial Password Manager application also provides the user with the option to randomly generate a password, as shown in <a href="#_Ref473718968" rel="nofollow">Figure 12</a>. It stands to reason that the user should be able to review that password before accepting it.<a name="_Ref473718968" id="_Ref473718968"> </a></p>
<p><img alt="Figure 12" src="https://software.intel.com/sites/default/files/managed/aa/65/sgx-tutorial-series-part-8-fig12.png" title="Figure 12" /></p>
<p><strong>Figure 12.</strong> <em>The interface for setting an account's password.</em></p>
<p>We follow the same approach of using <code>MessageBox()</code> to show the password, only with a slightly different twist. Instead of presenting a dialog box with a single OK button, we prompt the user, asking them if they accept the randomly generated password that is shown. Their options are:</p>
<ul><li><strong>Yes</strong>. Accepts and saves the password.</li>
<li><strong>No</strong>. Generates a new password using the same character requirements, and then reprompts.</li>
<li><strong>Cancel</strong>. Cancels the operation entirely, and does not change the password.</li>
</ul><p>This dialog box is shown in <a href="#_Ref473719069" rel="nofollow">Figure 13</a>.<a name="_Ref473719069" id="_Ref473719069"> </a></p>
<p><img alt="Figure 13" src="https://software.intel.com/sites/default/files/managed/8d/7c/sgx-tutorial-series-part-8-fig13.png" title="Figure 13" /></p>
<p><strong>Figure 13.</strong> <em>Accepting or rejecting a randomly generated password.</em></p>
<p>The code behind this dialog box, which implements the <code>accounts_generate_and_view_password()</code> method, is shown in <a href="#_Ref474934081" rel="nofollow">Figure 14</a>. The approach is very similar to <code>accounts_view_password</code>(), except there is additional logic to handle the button options in the dialog box.<a name="_Ref474934081" id="_Ref474934081"> </a></p>
<pre class="brush:csharp;">int PasswordManagerCoreNative::accounts_generate_and_view_password(UINT16 length, UINT16 flags, LPWSTR *wpass, UINT16 *wlen, HWND hWnd)
{
int rv;
char *cpass;
int dresult;
cpass = new char[length + 1];
if (cpass == NULL) return NL_STATUS_ALLOC;
if (supports_sgx()) rv = ew_accounts_generate_password(length, flags, cpass);
else rv = vault.accounts_generate_password(length, flags, cpass);
cpass[length] = NULL;
if (rv != NL_STATUS_OK) return rv;
*wpass = towchar(cpass, length + 1, wlen);
SecureZeroMemory(cpass, length);
delete[] cpass;
if (*wpass == NULL) return NL_STATUS_ALLOC;
// Show the message box
dresult= MessageBox(hWnd, *wpass, L"Accept this password?", MB_YESNOCANCEL);
if (dresult == IDNO) return NL_STATUS_AGAIN;
else if (dresult == IDCANCEL) return NL_STATUS_USER_CANCEL;
return NL_STATUS_OK;
}</pre>
<p><strong>Figure 14.</strong> <em>Code listing for <code>accounts_generate_and_view_password()</code> in PasswordManagerCoreNative.</em></p>
<p>The dialog result of IDNO is mapped to NL_STATUS_AGAIN, which is the “retry” option. A result of IDCANCEL is mapped to NL_STATUS_USER_CANCEL.</p>
<p>Because the wpass pointer is passed in from the parent method in <strong>PasswordManagerCore</strong>, we implement the retry loop there instead of in the native method. This is <em>slightly</em> less efficient, but it keeps the overall program architecture consistent. The code for <code>accounts_generate_and_view_password()</code> in <strong><code>PasswordManagerCore</code> </strong>is shown in <a href="#_Ref473723643" rel="nofollow">Figure 15</a>.<a name="_Ref473723643" id="_Ref473723643"> </a></p>
<pre class="brush:csharp;">int PasswordManagerCore::generate_and_view_password(UInt16 mlength, UInt16 mflags, SecureString ^%password, IntPtr hptr)
{
int rv = NL_STATUS_AGAIN;
LPWSTR wpass;
UINT16 wlen;
UINT16 length = mlength;
UINT16 flags = mflags;
HWND hWnd = static_cast&lt;HWND&gt;(hptr.ToPointer());
if (!length) return NL_STATUS_INVALID;
// Loop until they accept the randomly generated password, cancel, or an error occurs.
while (rv == NL_STATUS_AGAIN) {
rv = _nlink-&gt;accounts_generate_and_view_password(length, flags, &amp;wpass, &amp;wlen, hWnd);
// Each loop through here allocates a new pointer.
if ( rv == NL_STATUS_AGAIN ) _nlink-&gt;accounts_release_password(wpass, wlen);
}
if (rv != NL_STATUS_OK) return rv;
// They accepted this password, so assign it and return.
password-&gt;Clear();
for (int i = 0; i &lt; length; ++i) {
password-&gt;AppendChar(wpass[i]);
}
_nlink-&gt;accounts_release_password(wpass, wlen);
return rv;
}</pre>
<p><strong>Figure 15.</strong> <em>Code listing for <code>accounts_generate_and_view_password()</code> in PasswordManagerCore.</em></p>
<h2>Summary</h2>
<p>Mixing enclaves with managed code is a tricky, and potentially risky, business. As a general rule, secrets should not cross the enclave boundary unencrypted, but there are applications such as our Tutorial Password Manager where this cannot be avoided. In these cases, you must take proper care to not undermine the security that is provided by Intel SGX. Exposing secrets to unprotected memory can be a necessary evil, but placing them in managed memory can have disasterous consequences.</p>
<p>The takeaway from this part of the series should be this: <strong>Intel SGX does not eliminate the need for secure coding practices</strong>. What it gives you is a tool (and a very powerful one) for keeping your application’s secrets away from malicious software, but that tool, alone, does not and cannot build a secure application.</p>
<h2>Sample Code</h2>
<p>The code sample for this part of the series builds against the Intel SGX SDK version 1.7 using Microsoft Visual Studio* 2015.</p>
<h2>Coming Up Next</h2>
<p>In <a href="https://software.intel.com/en-us/articles/intel-sgx-tutorial-part-9-power-events-and-data-sealing">Part 9 of the series</a>, we’ll add support for power events. Stay tuned!</p>
Thu, 23 Feb 2017 16:39:32 -0800John M. (Intel)713868Overview of Intel Protected File System Library Using Software Guard Extensionshttps://software.intel.com/en-us/articles/overview-of-intel-protected-file-system-library-using-software-guard-extensions
<p align="center"><strong>Intel® Protected File System Library</strong></p>
<ul><li>A new feature called Intel Protection File System Library is introduced in the Intel SGX 1.7 Release. This Library is used to create, operate and delete files inside the enclave. To make use of the Intel Protected File system Library we need the following requirements:
<ul><li>Visual Studio 2015,</li>
<li>Intel SGX SDK version 1.7 </li>
<li>Intel SGX PSW version 1.7</li>
</ul></li>
<li>The above requirements are essential for implementing Intel SGX Protected File System. In this document we will discuss regarding the architecture, API’s, Implementation and Limitations of Intel Protected File System Library.</li>
</ul><p><strong>Overview of Intel® Protected File System Library:</strong></p>
<ul><li>Intel® Protected File System Library provides protected files API for Intel® SGX enclaves. It supports a basic subset of the regular C file API and enables you to create files and work with them as you would normally do from a regular application.</li>
<li>We have 15 file operation functions API’s provided by Intel SGX. These API work almost the same as the regular C file API.</li>
<li>With this API, the files are encrypted and saved on the untrusted disk during a write operation, and they are verified for confidentiality and integrity during a read operation.</li>
<li>To encrypt a file, you should provide a file encryption key. This key is a 128 bits key, and is used as a key derivation key, to generate multiple encryption keys.</li>
<li>The key derivation key used as an input to one of the key derivation functions is called a key derivation key, can be generated by an approved cryptographic random bit generator, or by an approved automated key establishment process. Another option is to use automatic keys derived from the enclave sealing key.</li>
<li>This way we can keep our files secure and safe inside the Enclave. Since our files are encrypted and stored they are safe and secure inside the enclave.</li>
</ul><p><strong>Intel Protected File System API:</strong></p>
<p>The Intel Protected File System Library provides the following functionalities.</p>
<ul><li>sgx_fopen</li>
<li>sgx_fopen_auto_key</li>
<li>sgx_fclose</li>
<li>sgx_fread</li>
<li>sgx_fwrite</li>
<li>sgx_fflush</li>
<li>sgx_ftell</li>
<li>sgx_fseek</li>
<li>sgx_feof</li>
<li>sgx_ferror</li>
<li>sgx_clearerr</li>
<li>sgx_remove</li>
<li>sgx_fexport_auto_key</li>
<li>sgx_fimport_auto_key</li>
<li>sgx_fclear_cache</li>
</ul><p>The above mentioned API’s are present in the SGX Protected FS trusted library. And these can be called only within the trusted enclave code which makes our files secure. </p>
<p><strong>Limitation</strong><strong> of Protected File System </strong></p>
<ol><li> Protected Files have meta-data embedded in them, only one file handle can be opened for writing at a time, or many file handles for reading.</li>
<li>Operating System protection mechanism is used for protecting against accidentally opening more than one ‘write’ file handle. If this protection is bypassed, the file will get corrupted.</li>
<li>An open file handle can be used by many threads inside the same enclave, the APIs include internal locks for handling this and the operations will be executed by one.</li>
</ol><p><span style="color:rgb(102, 102, 102)">Please find the detailed information in the PDF and also i have shared sample code for Intel Protected File System Library using SGX.</span></p>
Mon, 19 Dec 2016 21:56:59 -0800Selvaraj, Surenthar (Intel)706092CSharp Application with Intel Software Guard Extensionhttps://software.intel.com/en-us/articles/csharp-application-with-intel-software-guard-extension
<p align="center"><strong>C# Application with Intel Software Guard Extension</strong></p>
<p>Enclaves must be 100 percent native code and the enclave bridge functions must be 100 percent native code with C (and not C++) linkages, it is possible, indirectly, to make an ECALL into an enclave from .NET and to make an OCALL from an enclave into a .NET object.</p>
<p><strong>Mixing Managed Code and Native Code with C++/CLI</strong></p>
<p>Microsoft Visual Studio* 2005 and later offers three options for calling unmanaged code from managed code:</p>
<ul><li><strong>Platform Invocation Services, commonly referred to by developers as P/Invoke:</strong>
<ul><li>P/Invoke is good for calling simple C functions in a DLL, which makes it a reasonable choice for interfacing with enclaves, but writing P/Invoke wrappers and marshaling data can be difficult and error-prone.</li>
</ul></li>
<li><strong>COM:</strong>
<ul><li>COM is more flexible than P/Invoke, but it is also more complicated; that additional complexity is unnecessary for interfacing with the C bridge functions required by enclaves</li>
</ul></li>
<li><strong>C++/CLI:</strong>
<ul><li>C++/CLI offers significant convenience by allowing the developer to mix managed and unmanaged code in the same module, creating a mixed-mode assembly which can in turn be linked to modules comprised entirely of either managed or native code.</li>
<li>Data marshaling in C++/CLI is also fairly easy: for simple data types it is done automatically through direct assignment, and helper methods are provided for more complex types such as arrays and strings.</li>
<li>Data marshaling is, in fact, so painless in C++/CLI that developers often refer to the programming model as IJW (an acronym for “it just works”).</li>
<li>The trade-off for this convenience is that there can be a small performance penalty due to the extra layer of functions, and it does require that you produce an additional DLL when interfacing with Intel SGX enclaves.</li>
</ul></li>
</ul><p>Please find the detailed information in the PDF and also i have shared sample code.</p>
Tue, 13 Dec 2016 02:52:24 -0800Selvaraj, Surenthar (Intel)705198Intel® Software Guard Extensions Part 7: Refine the Enclave with Proxy Functionshttps://software.intel.com/en-us/articles/intel-software-guard-extensions-tutorial-part-7-refining-the-enclave
<p>Part 7 of the <a href="https://software.intel.com/en-us/sgx">Intel® Software Guard Extensions (Intel® SGX)</a> tutorial series revisits the enclave interface and adds a small refinement to make it simpler and more efficient. We’ll discuss how the proxy functions marshal data between unprotected memory space and the enclave, and we’ll also discuss one of the advanced features of the <a href="https://software.intel.com/sites/products/sgx-sdk-users-guide-windows/Content/Enclave%20Definition%20Language%20File%20Syntax.htm">Enclave Definition Language (EDL)</a> syntax.</p>
<p>You can find a list of all of the published tutorials in the article <a href="/en-us/articles/introducing-the-intel-software-guard-extensions-tutorial-series" rel="nofollow">Introducing the Intel® Software Guard Extensions Tutorial Series</a>.</p>
<p>Source code is provided with this installment of the series. With this release we have migrated the application to the 1.7 release of the Intel SGX SDK and also moved our development environment to Microsoft Visual Studio* Professional 2015.</p>
<h2>The Proxy Functions</h2>
<p>When building an enclave using the Intel SGX SDK you define the interface to the enclave in the EDL. The EDL specifies which functions are ECALLs (“enclave calls,” the functions that enter the enclave) and which ones are OCALLs (“outside calls,” the calls to untrusted functions from within the enclave).</p>
<p>When the project is built, the Edger8r tool that is included with the Intel SGX SDK parses the EDL file and generates a series of proxy functions. These proxy functions are essentially wrappers around the <em>real</em> functions that are prototyped in the EDL. Each ECALL and OCALL gets a pair of proxy functions: a trusted half and an untrusted half. The trusted functions go into <em>EnclaveProject_t.h</em> and <em>EnclaveProjct_t.c</em> and are included in the Autogenerated Files folder of your enclave project. The untrusted proxies go into <em>EnclaveProject_u.h</em> and <em>EnclaveProject_u.c</em> and are placed in the Autogenerated Files folder of the project that will be interfacing with your enclave.</p>
<p>Your program does not call the ECALL and OCALL functions directly; it calls the proxy functions. When you make an ECALL, you call the untrusted proxy function for the ECALL, which in turn calls the trusted proxy function inside the enclave. That proxy then calls the “real” ECALL and the return value propagates back to the untrusted function. This sequence is shown in Figure 1. When you make an OCALL, the sequence is reversed: you call the trusted proxy function for the OCALL, which calls an untrusted proxy function outside the enclave that, in turn, invokes the “real” OCALL.</p>
<p style="text-align:center"><img class="full-content-width" src="/sites/default/files/managed/76/01/enclave-development-part-7-fig-1.png" /><br /><strong>Figure 1.</strong> Proxy functions for an ECALL.</p>
<p>The proxy functions are responsible for:</p>
<ul><li>Marshaling data into and out of the enclave</li>
<li>Placing the return value of the <em>real</em> ECALL or OCALL in an address referenced by a pointer parameter</li>
<li>Returning the success or failure of the ECALL or OCALL itself as an <strong>sgx_status_t</strong> value</li>
</ul><p>Note that this means that each ECALL or OCALL has potentially two return values. There’s the success of the ECALL or OCALL itself, meaning, were we able to successfully enter or exit the enclave, and then the return value of the function being called in the ECALL or OCALL.</p>
<p>The EDL syntax for the ECALL functions <em>ve_lock()</em> and <em>ve_unlock()</em> in our Tutorial Password Manager’s enclave is shown below:</p>
<pre class="brush:cpp;">enclave {
trusted {
public void ve_lock ();
public int ve_unlock ([in, string] char *password);
}
}</pre>
<p>And here are the untrusted proxy function prototypes that are generated by the Edger8r tool:</p>
<pre class="brush:cpp;">sgx_status_t ve_lock(sgx_enclave_id_t eid);
sgx_status_t ve_unlock(sgx_enclave_id_t eid, int* retval, char* password);</pre>
<p>Note the additional arguments that have been added to the parameter list for each function and that the functions now return a type of <strong>sgx_status_t</strong>.</p>
<p>Both proxy functions need the enclave identifier, which is passed in the first parameter, eid. The <em>ve_lock()</em> function has no parameters and does not return a value so no further changes are necessary. The <em>ve_unlock()</em> function, however, does both. The second argument to the proxy function is a pointer to an address that will store the return value from the <em>real</em> ve_unlock() function in the enclave, in this case a return value of type <strong>int</strong>. The actual function parameter, <strong>char *</strong><em>password</em>, is included after that.</p>
<h2>Data Marshaling</h2>
<p>The untrusted portion of an application does not have access to enclave memory. It cannot read from or write to these protected memory pages. This presents some difficulties when the function parameters include pointers. OCALLs are especially problematic, because a memory allocated inside the enclave is not accessible to the OCALL, but even ECALLs can have issues. Enclave memory is mapped into the application’s memory space, so enclave pages can be adjacent to unprotected memory pages. If you pass a pointer to untrusted memory into an enclave, and then fail to do appropriate bounds checking in your enclave, you may inadvertently cross the enclave boundary when reading or writing to that memory in your ECALL.</p>
<p>The Intel SGX SDK’s solution to this problem is to copy the contents of data buffers into and out of enclaves, and have the ECALLs and OCALLs operate on these copies of the original memory buffer. When you pass a pointer into an enclave, you specify in the EDL whether the buffer referenced by the pointer is being pass into the call, out of the call, or in both directions, and then you specify the size of the buffer. The proxy functions generated by the Edger8r tool use this information to check that the address range does not cross the enclave boundary, copy the data into or out of the enclave as indicated, and then substitute a pointer to the copy of the buffer in place of the original pointer.</p>
<p>This is the slow-and-safe approach to marshaling data and pointers between unprotected memory and enclave memory. However, this approach has drawbacks that may make it undesirable in some cases:</p>
<ul><li>It’s slow, since each memory buffer is checked and copied.</li>
<li>It requires additional heap space in your enclave to store the copies of the data buffers.</li>
<li>The EDL syntax is a little verbose.</li>
</ul><p>There are also cases where you just need to pass a raw pointer into an ECALL and out to an OCALL without it ever being used inside the enclave, such as when passing a function pointer for a callback function straight through to an OCALL. In this case, there <em>is</em> no data buffer per se, just the pointer address itself, and the marshaling functions generated by Edger8r actually get in the way.</p>
<h2>The Solution: user_check</h2>
<p>Fortunately, the EDL language does support passing a raw pointer address into an ECALL or an OCALL, skipping both the boundary checks and the data buffer copy. The <code>user_check</code> parameter tells the Edger8r tool to pass a pointer as it is and assume that the developer has done the proper bounds checking on the address. When you specify <code>user_check</code> you are essentially trading safety for performance.</p>
<p>A pointer marked with the <code>user_check</code> does not have a direction (<code>in</code> or <code>out</code>) associated with it, because there is no buffer copy taking place. Mixing <code>user_check</code> with <code>in</code> or <code>out</code> will result in an error at compile time. Similarly, you don’t supply a <code>count</code> or <code>size</code> parameter, either.</p>
<p>In the Tutorial Password Manager, the most appropriate place to use the <code>user_check</code> parameter is in the ECALLs that load and store the encrypted password vault. While our <a href="/en-us/articles/intel-software-guard-extensions-tutorial-part-2-app-design" rel="nofollow">design constraints</a> put a practical limit on the size of the vault itself, generally speaking these sorts of bulk reads and writes benefit from allowing the enclave to directly operate on untrusted memory.</p>
<p>The original EDL for <em>ve_load_vault()</em> and <em>ve_get_vault()</em> looks like this:</p>
<pre class="brush:cpp;">public int ve_load_vault ([in, count=len] unsigned char *edata, uint32_t len);
public int ve_get_vault ([out, count=len] unsigned char *edata, uint32_t len);</pre>
<p>Rewriting these to specify <code>user_check</code> results in the following:</p>
<pre class="brush:cpp;">public int ve_load_vault ([user_check] unsigned char *edata);
public int ve_get_vault ([user_check] unsigned char *edata, uint32_t len);</pre>
<p>Notice that we were able to drop the <em>len</em> parameter from <em>ve_load_vault()</em>. As you might recall from <a href="/en-us/articles/software-guard-extensions-tutorial-series-part-4" rel="nofollow">Part 4</a>, the issue we had with this function was that although the length of the vault is stored as a variable in the enclave, the proxy functions don’t have access to it. In order for the ECALL’s proxy functions to copy the incoming data buffer, we had to supply the length in the EDL so that the Edger8r tool would know the size of the buffer. With the <code>user_check</code> option, there is no buffer copy operation, so this problem goes away. The enclave can read directly from untrusted memory, and it can use its internal variable to determine how many bytes to read.</p>
<p>However, we still send the length as a parameter to <em>ve_get_vault()</em>. This is a safety check to ensure that we don’t accidentally overflow a buffer when fetching the encrypted vault from the enclave.</p>
<h2>Summary</h2>
<p>The EDL provides three options for passing pointers into an ECALL or an OCALL: <code>in</code>, <code>out</code>, and <code>user_check</code>. These options are summarized in Table 1.</p>
<table><thead><tr><th>Specifier/Direction</th>
<th>ECALL</th>
<th>OCALL</th>
</tr></thead><tbody><tr><td><strong>in</strong></td>
<td>The buffer is copied from the application into the enclave. Changes will only affect the buffer inside the enclave.</td>
<td>The buffer is copied from the enclave to the application. Changes will only affect the buffer outside the enclave.</td>
</tr><tr><td><strong>out</strong></td>
<td>A buffer will be allocated inside the enclave and initialized with zeros. It will be copied to the original buffer when the ECALL exits.</td>
<td>A buffer will be allocated outside the enclave and initialized with zeros. This untrusted buffer will be copied to the original buffer in the enclave when the OCALL exits.</td>
</tr><tr><td><strong>in, out</strong></td>
<td>Data is copied back and forth.</td>
<td>Data is copied back and forth.</td>
</tr><tr><td><strong>user_check</strong></td>
<td>The pointer is not checked. The raw address is passed.</td>
<td>The pointer is not checked. The raw address is passed.</td>
</tr></tbody></table><p>Table 1. Pointer specifiers and their meanings in ECALLs and OCALLs.</p>
<p>If you use the direction indicators, the data buffer referenced by your pointer gets copied and you must supply a count so that the Edger8r can determine how many bytes are in the buffer. If you specify <code>user_check</code>, the raw pointer is passed to the ECALL or OCALL unaltered.</p>
<h2>Sample Code</h2>
<p>The code sample for this part of the series has been updated to build against the Intel SGX SDK version 1.7 using Microsoft Visual Studio 2015. It should still work with the Intel SGX SDK version 1.6 and Visual Studio 2013, but we encourage you to update to the newer release of the Intel SGX SDK.</p>
<h2>Coming Up Next</h2>
<p>In <a href="https://software.intel.com/en-us/articles/intel-sgx-tutorial-series-part-8-gui-integration">Part 8 of the series</a>, we’ll integrate the GUI with our application. Stay tuned!</p>
Mon, 28 Nov 2016 14:07:16 -0800John M. (Intel)704116Intel® Software Guard Extensions Part 6: How to Create Dual Code Pathshttps://software.intel.com/en-us/articles/intel-software-guard-extensions-tutorial-series-part-6-dual-code-paths
<p>In Part 6 of the <a href="https://software.intel.com/en-us/sgx">Intel® Software Guard Extensions (Intel® SGX)</a> tutorial series, we set aside the enclave to address an outstanding design requirement that was laid out in <a href="/en-us/articles/intel-software-guard-extensions-tutorial-part-2-app-design" rel="nofollow">Part 2, Application Design</a>: provide support for dual code paths. We want to make sure our Tutorial Password Manager will function on hosts both with and without Intel SGX capability. Much of the content in this part comes from the article, <a href="/en-us/articles/properly-detecting-intel-software-guard-extensions-in-your-applications" rel="nofollow">Properly Detecting Intel® Software Guard Extensions in Your Applications</a>.</p>
<p>You can find the list of all of the published tutorials in the article <a href="/en-us/articles/introducing-the-intel-software-guard-extensions-tutorial-series" rel="nofollow">Introducing the Intel® Software Guard Extensions Tutorial Series</a>.</p>
<p>There is source code provided with this installment of the series.</p>
<h2>All Intel® Software Guard Extensions Applications Need Dual Code Paths</h2>
<p>First it’s important to point out that all Intel SGX applications must have dual code paths. Even if an application is written so that it should <em>only</em> execute if Intel SGX is available and enabled, a fallback code path must exist so that you can present a meaningful error message to the user and then exit gracefully.</p>
<p>In short, <em>an application should never crash or fail to launch solely because the platform does not support Intel SGX.</em></p>
<h2>Scoping the Problem</h2>
<p>In <a href="/en-us/articles/intel-software-guard-extensions-tutorial-part-5-enclave-development" rel="nofollow">Part 5</a> of the series we completed our first version of our application enclave and tested it by hardcoding the enclave support to be on. That was done by setting the <em>_supports_sgx</em> flag in PasswordCoreNative.cpp.</p>
<pre class="brush:jscript;">PasswordManagerCoreNative::PasswordManagerCoreNative(void)
{
_supports_sgx= 1;
adsize= 0;
accountdata= NULL;
timer = NULL;
}</pre>
<p>Obviously, we can’t leave this on by default. The convention for feature detection is that features are off by default and turned on if they are detected. So our first step is to undo this change and set the flag back to 0, effectively disabling the Intel SGX code path.</p>
<pre class="brush:jscript;">PasswordManagerCoreNative::PasswordManagerCoreNative(void)
{
_supports_sgx= 0;
adsize= 0;
accountdata= NULL;
timer = NULL;
}</pre>
<p>However, before we get into the feature detection procedure, we’ll give the console application that runs our test suite, CLI Test App, a quick functional test by executing it on an older system that does not have the Intel SGX feature. With this flag set to zero, the application will not choose the Intel SGX code path and thus should run normally.</p>
<p>Here’s the output from a 4th generation Intel® Core™ i7 processor-based laptop, running Microsoft Windows* 8.1, 64-bit. This system does not support Intel SGX.</p>
<p><img alt="CLI Test App" src="/sites/default/files/managed/d0/56/cli-test-app.png" title="CLI Test App" /></p>
<h2>What Happened?</h2>
<p>Clearly we have a problem even when the Intel SGX code path is explicitly disabled in the software. This application, as written, cannot execute on a system without Intel SGX support. It didn’t even <em>start</em> executing. So what’s going on?</p>
<p>The clue in this case comes from the error message in the console window:</p>
<p class="greyHighlight"><code>System.IO.FileNotFoundException: Could not load file or assembly ‘PasswordManagerCore.dll’ or one of its dependencies. The specified file could not be found.</code></p>
<p>Let’s take a look at PasswordManagerCore.dll and its dependencies:</p>
<p><img alt="Additional Dependencies" src="https://software.intel.com/sites/default/files/managed/36/30/bcrypt-lib.jpg.png" title="Additional Dependencies" /></p>
<p>In addition to the core OS libraries, we have dependencies on <code>bcrypt.lib and EnclaveBridge.lib</code>, which will require <code>bcrypt.dll</code> and <code>EnclaveBridge.dll</code> at runtime. Since <code>bcrypt.dll</code> comes from Microsoft and is included in the OS, we can reasonably assume its dependencies, if any, are already installed. That leaves <code>EnclaveBridge.dll.</code></p>
<p>Examining its dependencies, we see the following:</p>
<p><img alt="Additional Dependencies" src="https://software.intel.com/sites/default/files/managed/23/29/sgx-urts-lib.png" title="Additional Dependencies" /></p>
<p>This is the problem. Even though we have the Intel SGX code path explicitly disabled, <code>EnclaveBridge.dll</code> still has references to the Intel SGX runtime libraries. All symbols in an object module <em>must</em> be resolved as soon as it is loaded. It doesn’t matter if we disable the Intel SGX code path: undefined symbols are still present in the DLL. When <code>PasswordManagerCore.dll</code> loads, it resolves its undefined symbols by loading <code>bcrypt.dll</code> and <code>EnclaveBridge.dll</code>, the latter of which, in turn, attempts to resolve <em>its</em> undefined symbols by loading <code>sgx_urts.dll</code> and <code>sgx_uae_service.dll</code>. The system we tried to run our command-line test application on does not have these libraries, and since the OS can’t resolve all of the symbols it throws an exception and the program crashes before it even starts.</p>
<p>These two DLLs are part of the Intel SGX Platform Software (PSW) package, and without them Intel SGX applications written using the Intel SGX Software Development Kit (SDK) cannot execute. Our application needs to be able to run even if these libraries are not present.</p>
<h2>The Platform Software Package</h2>
<p>As mentioned above, the runtime libraries are part of the PSW. In addition to these support libraries, the PSW includes:</p>
<ul><li>Services that support and maintain the trusted compute block (TCB) on the system</li>
<li>Services that perform and manage certain Intel SGX operations such as attestation</li>
<li>Interfaces to platform services such as trusted time and the monotonic counters</li>
</ul><p>The PSW must be installed by the application installer when deploying an Intel SGX application, because Intel does not offer the PSW for direct download by end users. Software vendors must not assume that it will already be present and installed on the destination system. In fact, the <a href="/en-us/articles/intel-sgx-product-licensing" rel="nofollow">license agreement for Intel SGX</a> specifically states that licensees must re-distribute the PSW with their applications.</p>
<p>We’ll discuss the PSW installer in more detail in a future installment of the series covering packaging and deployment.</p>
<h2>Detecting Intel Software Guard Extensions Support</h2>
<p>So far we’ve focused on the problem of just <em>starting</em> our application on systems without Intel SGX support, and more specifically, without the PSW. The next step is to detect whether or not Intel SGX support is present and enabled once the application is running.</p>
<p>Intel SGX feature detection is, unfortunately, a complicated procedure. For a system to be Intel SGX capable, four conditions must be met:</p>
<ol><li>The CPU must support Intel SGX.</li>
<li>The BIOS must support Intel SGX.</li>
<li>In the BIOS, Intel SGX must be explicitly enabled or set to the “software controlled” state.</li>
<li>The PSW must be installed on the platform.</li>
</ol><p>Note that the CPUID instruction, alone, is not sufficient to detect the usability of Intel SGX on a platform. It can tell you whether or not the CPU supports the feature, but it doesn’t know anything about the BIOS configuration or the software that is installed on a system. Relying solely on the CPUID results to make decisions about Intel SGX support can potentially lead to a runtime fault.</p>
<p>To make feature detection even more difficult, examining the state of the BIOS is not a trivial task and is generally not possible from a user process. Fortunately the Intel SGX SDK provides a simple solution: the function sgx_enable_device will both check for Intel SGX capability and attempt to enable it if the BIOS is set to the software control state (the purpose of the software control setting is to allow applications to enable Intel SGX without requiring users to reboot their systems and enter their BIOS setup screens, a particularly daunting and intimidating task for non-technical users).</p>
<p>The problem with sgx_enable_device, though, is that it is part of the Intel SGX runtime, which means the PSW must be installed on the system in order to use it. So before we attempt to call sgx_enable_device, we must first detect whether or not the PSW is present.</p>
<h2>Implementation</h2>
<p>With our problem scoped out, we can now lay out the steps that must be followed, in order, for our dual-code path application to function properly. Our application must:</p>
<ol><li>Load and begin executing even without the Intel SGX runtime libraries.</li>
<li>Determine whether or not the PSW package is installed.</li>
<li>Determine whether or not Intel SGX is enabled (and attempt to enable it).</li>
</ol><h2>Loading and Executing without the Intel Software Guard Extensions Runtime</h2>
<p>Our main application depends on PasswordManagerCore.dll, which depends on EnclaveBridge.dll, which in turn depends on the Intel SGX runtime. Since all symbols need to be resolved when an application loads, we need a way to prevent the loader from trying to resolve symbols that come from the Intel SGX runtime libraries. There are two options:</p>
<h4>Option #1: Dynamic Loading </h4>
<p>In dynamic loading, you don’t explicitly link the library in the project. Instead you use system calls to load the library at runtime and then look up the names of each function you plan to use in order to get the addresses of where they have been placed in memory. Functions in the library are then invoked indirectly via function pointers.</p>
<p>Dynamic loading is a hassle. Even if you only need a handful of functions, it can be a tedious process to prototype function pointers for every function that is needed and get their load address, one at a time. You also lose some of the benefits provided by the integrated development environment (such as prototype assistance) since you are no longer explicitly calling functions by name.</p>
<p>Dynamic loading is typically used in extensible application architectures (for example, plug-ins).</p>
<h4>Option #2: Delayed-Loaded DLLs</h4>
<p>In this approach, you dynamically link all your libraries in the project, but instruct Windows to do delayed loading of the problem DLL. When a DLL is delay-loaded, Windows does not attempt to resolve symbols that are defined by that DLL when the application starts. Instead it waits until the program makes its first call to a function that is defined in that DLL, at which point the DLL is loaded and the symbols get resolved (along with any of <em>its </em>dependencies). What this means is that a DLL is not loaded until the application needs it. A beneficial side effect of this approach is that it allows applications to reference a DLL that is not installed, so long as no functions in that DLL are ever called.</p>
<p>When the Intel SGX feature flag is off, that is exactly the situation we are in so we will go with option #2.</p>
<p>You specify the DLL to be delay-loaded in the project configuration for the dependent application or DLL. For the Tutorial Password Manager, the best DLL to mark for delayed loading is EnclaveBridge.dll as we only call this DLL if the Intel SGX path is enabled. If this DLL doesn’t load, neither will the two Intel SGX runtime DLLS.</p>
<p>We set the option in the <strong>Linker -&gt; Input</strong> page of the PasswordManagerCore.dll project configuration:</p>
<p><img alt="Password Manager" src="https://software.intel.com/sites/default/files/managed/92/91/password-manager.png" title="Password Manager" /></p>
<p>After the DLL is rebuilt and installed on our 4th generation Intel Core processor system, the console test application works as expected.</p>
<p><img alt="CLI Test App" src="https://software.intel.com/sites/default/files/managed/0e/45/user-cli-test-app.png" title="CLI Test App" /></p>
<h2>Detecting the Platform Software Package</h2>
<p>Before we can call the sgx_enable_device function to check for Intel SGX support on the platform, we first have to make sure that the PSW package is installed because sgx_enable_device is part of the Intel SGX runtime. The best way to do this is to actually try to load the runtime libraries.</p>
<p>We know from the previous step that we can’t just dynamically link them because that will cause an exception when we attempt to run the program on a system that does not support Intel SGX (or have the PSW package installed). But we also can’t rely on delay-loaded DLLs either: delayed loading can’t tell us if a library is installed because if it isn’t, the application will still crash! That means we must use dynamic loading to test for the presence of the runtime libraries.</p>
<p>The PSW runtime libraries should be installed in the Windows system directory so we’ll use GetSystemDirectory to get that path, and limit the DLL search path via a call to SetDllDirectory. Finally, the two libraries will be loaded using LoadLibrary. If either of these calls fail, we know the PSW is not installed and that the main application should not attempt to run the Intel SGX code path.</p>
<h2>Detecting and Enabling Intel Software Guard Extensions</h2>
<p>Since the previous step dynamically loads the PSW runtime libraries, we can just look up the symbol for sgx_enable_device manually and then invoke it via a function pointer. The result will tell us whether or not Intel SGX is enabled.</p>
<h2>Implementation</h2>
<p>To implement this in the Tutorial Password Manager we’ll create a new DLL called FeatureSupport.dll. We can safely dynamically link this DLL from the main application since it has no explicit dependencies on other DLLs.</p>
<p>Our feature detection will be rolled into a C++/CLI class called FeatureSupport, which will also include some high-level functions for getting more information about the state of Intel SGX. In rare cases, enabling Intel SGX via software may require a reboot, and in rarer cases the software enable action fails and the user may be forced to enable it explicitly in their BIOS.</p>
<p>The class declaration for FeatureSupport is shown below.</p>
<pre class="brush:cpp;">typedef sgx_status_t(SGXAPI *fp_sgx_enable_device_t)(sgx_device_status_t *);
public ref class FeatureSupport {
private:
UINT sgx_support;
HINSTANCE h_urts, h_service;
// Function pointers
fp_sgx_enable_device_t fp_sgx_enable_device;
int is_psw_installed(void);
void check_sgx_support(void);
void load_functions(void);
public:
FeatureSupport();
~FeatureSupport();
UINT get_sgx_support(void);
int is_enabled(void);
int is_supported(void);
int reboot_required(void);
int bios_enable_required(void);
// Wrappers around SGX functions
sgx_status_t enable_device(sgx_device_status_t *device_status);
};</pre>
<p>Here are the low-level routines that check for the PSW package and attempt to detect and enable Intel SGX.</p>
<pre class="brush:cpp;">int FeatureSupport::is_psw_installed()
{
_TCHAR *systemdir;
UINT rv, sz;
// Get the system directory path. Start by finding out how much space we need
// to hold it.
sz = GetSystemDirectory(NULL, 0);
if (sz == 0) return 0;
systemdir = new _TCHAR[sz + 1];
rv = GetSystemDirectory(systemdir, sz);
if (rv == 0 || rv &gt; sz) return 0;
// Set our DLL search path to just the System directory so we don't accidentally
// load the DLLs from an untrusted path.
if (SetDllDirectory(systemdir) == 0) {
delete systemdir;
return 0;
}
delete systemdir; // No longer need this
// Need to be able to load both of these DLLs from the System directory.
if ((h_service = LoadLibrary(_T("sgx_uae_service.dll"))) == NULL) {
return 0;
}
if ((h_urts = LoadLibrary(_T("sgx_urts.dll"))) == NULL) {
FreeLibrary(h_service);
h_service = NULL;
return 0;
}
load_functions();
return 1;
}
void FeatureSupport::check_sgx_support()
{
sgx_device_status_t sgx_device_status;
if (sgx_support != SGX_SUPPORT_UNKNOWN) return;
sgx_support = SGX_SUPPORT_NO;
// Check for the PSW
if (!is_psw_installed()) return;
sgx_support = SGX_SUPPORT_YES;
// Try to enable SGX
if (this-&gt;enable_device(&amp;sgx_device_status) != SGX_SUCCESS) return;
// If SGX isn't enabled yet, perform the software opt-in/enable.
if (sgx_device_status != SGX_ENABLED) {
switch (sgx_device_status) {
case SGX_DISABLED_REBOOT_REQUIRED:
// A reboot is required.
sgx_support |= SGX_SUPPORT_REBOOT_REQUIRED;
break;
case SGX_DISABLED_LEGACY_OS:
// BIOS enabling is required
sgx_support |= SGX_SUPPORT_ENABLE_REQUIRED;
break;
}
return;
}
sgx_support |= SGX_SUPPORT_ENABLED;
}
void FeatureSupport::load_functions()
{
fp_sgx_enable_device = (fp_sgx_enable_device_t)GetProcAddress(h_service, "sgx_enable_device");
}
// Wrappers around SDK functions so the user doesn't have to mess with dynamic loading by hand.
sgx_status_t FeatureSupport::enable_device(sgx_device_status_t *device_status)
{
check_sgx_support();
if (fp_sgx_enable_device == NULL) {
return SGX_ERROR_UNEXPECTED;
}
return fp_sgx_enable_device(device_status);
}</pre>
<h2>Wrapping Up</h2>
<p>With these code changes, we have integrated Intel SGX feature detection into our application! It will execute smoothly on systems both with and without Intel SGX support and choose the appropriate code branch.</p>
<p>As mentioned in the introduction, there is sample code provided with this part for you to download. The attached archive includes the source code for the Tutorial Password Manager core, including the new feature detection DLL. Additionally, we have added a new GUI-based test program that automatically selects the Intel SGX code path, but lets you disable it if desired (this option is only available if Intel SGX is supported on the system).</p>
<p><img alt="SGX Code Branch" src="https://software.intel.com/sites/default/files/managed/fe/bc/sgx-code-branch.png" title="SGX Code Branch" /></p>
<p>The console-based test program has also been updated to detect Intel SGX, though it cannot be configured to turn it off without modifying the source code.</p>
<h2>Coming Up Next</h2>
<p>We’ll <a href="https://software.intel.com/en-us/articles/intel-software-guard-extensions-tutorial-part-7-refining-the-enclave">revisit the enclave in Part 7</a> in order to fine-tune the interface. Stay tuned!</p>
Fri, 28 Oct 2016 08:53:25 -0700John M. (Intel)700434