Files
intel-linux-sgx/sdk/protected_code_loader/pcl_entry.cpp
Li, Xun 321a6580fb Linux 2.16 Open Source Gold Release
Upgraded to OpenSSL 1.1.1m.
Provided RA-TLS (Remote Attestation based Transport Layer Security) APIs and
  Samples.
Supported PKRU (Protection Key rights Register) in Enclave.
Added APIs of SHA384 and VerifyReport2 to support TDX.
Enhanced QPL (Quote Provider Library) to support caching Intel PCK
  (Provisioning Certificate Key) certificate chain in local memory, or
  retrieving Intel PCK cert chain from local HTTP/S address.
Upgraded Intel ECDSA Quote Verification Enclave to integrate SgxSSL/OpenSSL
  version 1.1.1m.
Introduced Intel ID enclave for QE identity generation.
Fixed bugs.

Signed-off-by: Li, Xun <xun.li@intel.com>
2022-04-06 12:06:27 +08:00

203 lines
6.9 KiB
C++

/*
* Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <sgx_tseal.h>
#include <sgx_lfence.h>
#include <pcl_common.h>
#include <pcl_internal.h>
#include "rts.h"
/*
* g_tbl holds the PCL table. Its content is set by enclave encryption tool at build time
* It is located in its own section (PCLTBL_SECTION_NAME) so that
* enclave encryption tool can find it.
*/
pcl_table_t g_tbl __attribute__((section(PCLTBL_SECTION_NAME))) =
{
.pcl_state = PCL_PLAIN,
.reserved1 = {},
.pcl_guid = {},
.sealed_blob_size = 0 ,
.reserved2 = {},
.sealed_blob = {},
.decryption_key_hash = {},
.num_rvas = 0 ,
.reserved3 = {},
.rvas_sizes_tags_ivs = {}
};
/*
* g_pcl_imagebase is set at runtime to ELF base address.
* It is used by functions pcl_is_outside_enclave and pcl_is_within_enclave
*/
uintptr_t g_pcl_imagebase = 0;
/*
* @func pcl_entry is the PCL entry point. It is called from init_enclave in
* trusted runtime entry point. It extracts the decryption key from the sealed blob
* and use it to decrypt the encrypted portions of the enclave binary.
* @param INOUT void* elf_base, base address of enclave
* @param IN void* ms, the marshaling struture passed by urts
* @return sgx_status_t
* SGX_ERROR_UNEXPECTED if
* 1. Table inconsistencies:
* a. PCL state in PCL table is not PCL_CIPHER
* b. PCL_SEALED_BLOB_MAX_SIZE < tbl->sealed_blob_size
* 2. pcl_unseal_data returns incorrect values for either guid size or key size
* Respective error returned from pcl_unseal_data, pcl_sha256, pcl_gcm_decrypt or pcl_increment_iv
* SGX_SUCCESS if successfull
*/
sgx_status_t pcl_entry(void* elf_base, void* ms)
{
sgx_status_t ret = SGX_SUCCESS;
pcl_table_t* tbl = &g_tbl;
int memcmpret = 0;
sgx_sha256_hash_t hash = {0};
sgx_aes_gcm_128bit_key_t key = {0};
// Verify PCL state:
if(PCL_CIPHER != tbl->pcl_state)
{
return SGX_ERROR_UNEXPECTED;
}
tbl->pcl_state = PCL_RUNNING;
// ELF base address used by pcl_is_outside_enclave and pcl_is_within_enclave
g_pcl_imagebase = (uintptr_t)elf_base;
// Get key from sealed blob:
uint32_t guid_size = SGX_PCL_GUID_SIZE;
uint32_t key_size = SGX_AESGCM_KEY_SIZE;
// Verify the buffer size:
if(PCL_SEALED_BLOB_SIZE != tbl->sealed_blob_size)
{
return SGX_ERROR_UNEXPECTED;
}
system_features_t * csi = (system_features_t *)ms;
if(!(pcl_is_outside_enclave(csi, sizeof(*csi))))
{
return SGX_ERROR_UNEXPECTED;
}
sgx_lfence();
void *sealed_blob = csi->sealed_key;
if(NULL == sealed_blob)
{
return SGX_ERROR_UNEXPECTED;
}
if(!(pcl_is_outside_enclave(sealed_blob, PCL_SEALED_BLOB_SIZE)))
{
return SGX_ERROR_UNEXPECTED;
}
// LFENCE after boundary check
sgx_lfence();
// Copy sealed blob into enclave binary.
pcl_memcpy(tbl->sealed_blob, sealed_blob, PCL_SEALED_BLOB_SIZE);
// Unseal the sealed blob:
ret = pcl_unseal_data(
(const sgx_sealed_data_t*)tbl->sealed_blob, // Sealed data
tbl->pcl_guid, // AAD buffer
&guid_size, // pointer to AAD buffer length
key, // Resulting key
&key_size); // Size of resulting key
if(SGX_SUCCESS != ret)
{
goto Label_erase_key;
}
if((sizeof(tbl->pcl_guid) != guid_size) ||
(sizeof(key) != key_size ))
{
ret = SGX_ERROR_UNEXPECTED;
goto Label_erase_key;
}
// Verify key hash matches:
ret = pcl_sha256(key, SGX_AESGCM_KEY_SIZE, hash);
if(SGX_SUCCESS != ret)
{
goto Label_erase_key;
}
memcmpret = pcl_consttime_memequal(hash, tbl->decryption_key_hash, sizeof(sgx_sha256_hash_t));
pcl_volatile_memset((volatile void*)hash, 0, sizeof(sgx_sha256_hash_t)); // Scrub hash
if(1 != memcmpret)
{
ret = SGX_ERROR_PCL_SHA_MISMATCH;
goto Label_erase_key;
}
for(uint32_t i = 0;i< tbl->num_rvas;i++)
{
size_t size = tbl->rvas_sizes_tags_ivs[i].size;
unsigned char* ciphertext = (unsigned char *)((uint64_t)elf_base + tbl->rvas_sizes_tags_ivs[i].rva);
unsigned char* plaintext = ciphertext; // decrypt in place
unsigned char* tag = (unsigned char *)&(tbl->rvas_sizes_tags_ivs[i].tag);
unsigned char* iv = (unsigned char *)&(tbl->rvas_sizes_tags_ivs[i].iv.val);
// Verify ciphertext is inside the enclave:
if(!(pcl_is_within_enclave(ciphertext, size)))
{
ret = SGX_ERROR_UNEXPECTED;
goto Label_erase_key;
}
ret = pcl_gcm_decrypt(plaintext, ciphertext, size, NULL, 0, key, iv, tag);
if(SGX_SUCCESS != ret)
{
goto Label_erase_key;
}
}
// Return success:
ret = SGX_SUCCESS;
Label_erase_key:
// Erase key:
pcl_volatile_memset((volatile void*)key, 0, sizeof(sgx_aes_gcm_128bit_key_t));
tbl->pcl_state = PCL_DONE;
return ret;
}
/*
* @func pcl_bswap32 swaps a 32bit value endianity
* @param uint32_t val, input value
* @return uint32_t, val in opposite endianity
*/
uint32_t pcl_bswap32(uint32_t val)
{
uint32_t ret=(val);
asm ("bswap %0":"+r"(ret));
return ret;
}