Intel SGX Sealing
Contents

There is a few information related to sealing, even no detailed explanation in the paper: Intel SGX explaned. All in this post are from Intel, with a little thought of mine.

Sealing

Sealing is a service that Intel provides with Intel SGX technology for secure data saving.
Intel SGX provides protections data only if it is in the enclave, part of main memory. Therefore, when the enclave process exits, the enclave will be destroyed and any data that is secured whithin the enclave will be lost. If the data is meant to be re-used later, the enclave must make special arrangements to store the data outside the enclave.

Using sealing, the data within the enclave is encrypted using an encryption key that is derived from the CPU hardware. The encryption provides assurances of confidentiality, integrity, and authenticity on the data.

Note: Like Intel SGX does, sealing does not provide availability to the sealed data. Therefore, the data may be lost due to disk corruption, malicious modification (e.g. Ransomeware), etc.

Intel SGX provides two policies for encryption keys: MRENCLAVE (enclave identity) and MRSIGNER (signing identity). These policies affect the derivation of the encryption key, and this is partially explained in Intel SGX explained.

MRENCLAVE

Derive a key based on the value of the enclave’s MRENCLAVE. Any change that impacts the enclave’s measurement will yield a different key, providing full isolation between enclaves.
The paper also mentions that “different versions of the same enclave will also have different seal keys, preventing offline data migration.” In other words, the MRENCLAVE-based keys are available only to enclave instances sharing the same MRENCLAVE.

MRSIGNER

Derive a key based on the value of the enclave’s MRSIGNER, and the enclave’s version. MRSIGNER reflects the key or identity of the Sealing Authority that signed the enclave’s certificate. The Sealing Authority may sign multiple enclaves and enable them to retrieve the same seal key. These enclaves can transparently access data that was sealed by the other.

While sealing with MRENCLAVE does not allow offline data migration between the same enclave with different versions, this allows limited data migration (only older version to newer version) or between different enclaves with the same Signing identity.

The MRSIGNER-based keys are bound to the 3 tuples (MRSIGNER, ISVPRODID, ISVSVN). The keys are available to any enclave with:

Here, different version seems to mean different Security Version Number (SVN), which is explained in the paper Intel SGX explained (p79).

isvsvn

Enclaves that represent different versions of a module can have different security version numbers (SVN). The SGX design disallows the migration of secrets from an enclave with a higher SVN to an enclave with a lower SVN.

As users upgrade, SGX will facilitate the migration of secrets from the vulnerable version of the enclave to the fixed version. Once a user’s secrets have migrated, the SVN restrictions in SGX will deflect any attack based on building the vulnerable enclave version and using it to read the migrated secrets.

As explained above, a software module’s SVN should only be incremented when a security vulnerability is found. SIGSTRUCT only allocates 2 bytes to the ISVSVN field, which translates to 65,536 possible SVN values. This space can be exhausted if a large team (incorrectly) sets up a continuous build system to allocate a new SVN for every software build that it produces, and each code change triggers a build.

SDK Functions

Intel SGX SDK provides some functions for data sealing.

SDK function introduction is [here].

A very simple example data sealing code is as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sgx_status_t res;
uint8_t* plaintext = (uint8_t*) malloc(plaintext_len);
// Do something in plaintext memory space.

// Allocate space for sealing
uint32_t ciph_size = sgx_calc_sealed_data_size(0, plaintext_len);
uint8_t* sealed = (uint8_t*) malloc(ciph_size);
uint32_t plain_size = plaintext_len;

// Seal and unseal the data
res = sgx_seal_data(0, NULL, plaintext_len, plaintext, ciph_size, (sgx_sealed_data_t *) sealed);
assert(res == SGX_SUCCESS);

res = sgx_unseal_data((sgx_sealed_data_t *) sealed, NULL, NULL, plaintext, &plain_size);
assert (res == SGX_SUCCESS);

References