Skip to content

Commit

Permalink
Merge pull request #653 from fortanix/ns/RTE-107
Browse files Browse the repository at this point in the history
PPID decryption tool
  • Loading branch information
nshyrei authored Nov 19, 2024
2 parents 7943f02 + 25e0348 commit 6dafc6c
Show file tree
Hide file tree
Showing 11 changed files with 818 additions and 0 deletions.
126 changes: 126 additions & 0 deletions intel-sgx/ppid-retrieval-tool/Enclave/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Copyright (c) Fortanix, Inc.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

CC = gcc
AR = ar
LD = gcc
EDGER = sgx_edger8r
SIGNER = sgx_sign
INCLUDE = -I${SGX_SDK}/include \
-I${SGX_SDK}/include/tlibc
T_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g
U_CFLAGS = $(CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector -g
AR_FLAGS = rcs
OBJECTS = ppid.o
LIB_SGX_TRTS = -lsgx_trts
LIB_SGX_TSERVICE = -lsgx_tservice

ENCLAVE_LIBS = $(LIB_SGX_TRTS)
ENCLAVE_LIB_PARTS = -lsgx_tstdc -lsgx_tcrypto $(LIB_SGX_TSERVICE)
ENCLAVE = ppid
PRIVATE_KEY = private_key.pem
PUBLIC_KEY = public_key.pem
KEY_SIZE = 3072
ENCLAVE_EDL = $(ENCLAVE).edl
ENCLAVE_CONFIG = $(ENCLAVE).config.xml
OUTPUT_T = $(ENCLAVE).so
OUTPUT_T_UNSIG = $(ENCLAVE).unsigned.so
OUTPUT_U = lib$(ENCLAVE)_proxy.a
LIB_DIRS = -L ${SGX_SDK}/lib64
LD_FLAGS = -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles \
-Wl,--whole-archive -Wl,--start-group $(ENCLAVE_LIBS) -Wl,--end-group \
-Wl,--no-whole-archive -Wl,--start-group $(ENCLAVE_LIB_PARTS) -Wl,--end-group \
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
-Wl,--defsym,__ImageBase=0
TRUSTED_OBJECTS = $(ENCLAVE)_t.o
UNTRUSTED_OBJECTS = $(ENCLAVE)_u.o
TRUSTED_CODE = $(ENCLAVE)_t.h $(ENCLAVE)_t.c
UNTRUSTED_CODE = $(ENCLAVE)_u.h $(ENCLAVE)_u.c

#.SILENT:
all: $(OUTPUT_T) $(OUTPUT_U)

$(OUTPUT_T) : $(TRUSTED_OBJECTS) $(OBJECTS)
echo "$(INDENT)[LD] " $(OBJECTS) $(TRUSTED_OBJECTS) $(ENCLAVE_LIBS) $(ENCLAVE_LIBS_PARTS) $(OUTPUT_T_UNSIG)
$(LD) $(OBJECTS) $(TRUSTED_OBJECTS) $(LD_FLAGS) $(LIB_DIRS) -o $(OUTPUT_T_UNSIG)

echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)"

# generate 3072 bit private RSA key
openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE)

echo "$(INDENT)[EXT] $(PUBLIC_KEY)"
# extract public key
openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY)

echo "$(INDENT)[SGN]" $(OUTPUT_T_UNSIG)
$(SIGNER) sign -key $(PRIVATE_KEY) -enclave $(OUTPUT_T_UNSIG) -out $(OUTPUT_T) -config $(ENCLAVE_CONFIG) > /dev/null 2> /dev/null

$(OUTPUT_U) : $(UNTRUSTED_OBJECTS)
echo "$(INDENT)[AR] " $(OUTPUT_U)
$(AR) $(AR_FLAGS) $(OUTPUT_U) $(UNTRUSTED_OBJECTS)

%_t.o : $(subst .o,.c,$@) edger
echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(trusted edge)"
touch $(subst .o,.c,$@)
$(CC) -c $(INCLUDE) $(T_CFLAGS) $(subst .o,.c,$@)

%_u.o : $(subst .o,.c,$@) edger
echo "$(INDENT)[CC] " $(subst .o,.c,$@) "(untrusted edge)"
touch $(subst .o,.c,$@)
$(CC) -c $(INCLUDE) $(U_CFLAGS) $(subst .o,.c,$@)

%.o : %.c edger
echo "$(INDENT)[CC] " $< "(core)"
$(CC) $(INCLUDE) $(T_CFLAGS) -c $<

edger: $(ENCLAVE).edl
echo "$(INDENT)[GEN]" $(EDGER) $(ENCLAVE_EDL)
$(EDGER) $(ENCLAVE_EDL)

.PHONY: force_check
force_check:
true

.PHONY: scrub
scrub:
echo "$(INDENT)[RM] " $(PRIVATE_KEY) $(PUBLIC_KEY)
$(RM) $(PRIVATE_KEY) $(PUBLIC_KEY)

.PHONY: configure
configure:
echo "$(INDENT)[GEN] $(PRIVATE_KEY) ($(KEY_SIZE) bits)"

# generate 3072 bit private RSA key
openssl genrsa -out $(PRIVATE_KEY) -3 $(KEY_SIZE)

echo "$(INDENT)[EXT] $(PUBLIC_KEY)"
# extract public key
openssl rsa -in $(PRIVATE_KEY) -pubout -out $(PUBLIC_KEY)

.PHONY: clean
clean:
echo "$(INDENT)[RM]" $(OBJECTS)
$(RM) $(OBJECTS)

echo "$(INDENT)[RM]" $(OUTPUT_T_UNSIG) $(OUTPUT_T)
$(RM) $(OUTPUT_T_UNSIG) $(OUTPUT_T)

echo "$(INDENT)[RM]" $(TRUSTED_OBJECTS)
$(RM) $(TRUSTED_OBJECTS)

echo "$(INDENT)[RM]" $(TRUSTED_CODE)
$(RM) $(TRUSTED_CODE)

echo "$(INDENT)[RM]" $(UNTRUSTED_OBJECTS)
$(RM) $(UNTRUSTED_OBJECTS)

echo "$(INDENT)[RM]" $(UNTRUSTED_CODE)
$(RM) $(UNTRUSTED_CODE)

echo "$(INDENT)[RM]" $(OUTPUT_U)
$(RM) $(OUTPUT_U)
237 changes: 237 additions & 0 deletions intel-sgx/ppid-retrieval-tool/Enclave/ppid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
/* Copyright (c) Fortanix, Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <string.h>
#include <inttypes.h>
#include <sgx_error.h>
#include <sgx_quote_3.h>
#include <sgx_utils.h>
#include <sgx_tcrypto.h>
#include <sgx_trts.h>
#include <stdlib.h>
#include "../pce/pce_cert.h"
#include "ppid_t.h"

#define REF_N_SIZE_IN_BYTES 384
#define REF_E_SIZE_IN_BYTES 4
#define REF_D_SIZE_IN_BYTES 384
#define REF_P_SIZE_IN_BYTES 192
#define REF_Q_SIZE_IN_BYTES 192
#define REF_DMP1_SIZE_IN_BYTES 192
#define REF_DMQ1_SIZE_IN_BYTES 192
#define REF_IQMP_SIZE_IN_BYTES 192

#define REF_RSA_OAEP_3072_MOD_SIZE 384 //hardcode n size to be 384
#define REF_RSA_OAEP_3072_EXP_SIZE 4 //hardcode e size to be 4

/** Structure definition of the RSA key used to decrypt the PCE's PPID */
typedef struct _pce_rsaoaep_3072_encrypt_pub_key_t {
uint8_t n[REF_RSA_OAEP_3072_MOD_SIZE]; ///< RSA 3072 public modulus
uint8_t e[REF_RSA_OAEP_3072_EXP_SIZE]; ///< RSA 3072 public exponent
} pce_rsaoaep_3072_encrypt_pub_key_t;

#define REF_N_SIZE_IN_UINT REF_N_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_E_SIZE_IN_UINT REF_E_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_D_SIZE_IN_UINT REF_D_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_P_SIZE_IN_UINT REF_P_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_Q_SIZE_IN_UINT REF_Q_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_DMP1_SIZE_IN_UINT REF_DMP1_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_DMQ1_SIZE_IN_UINT REF_DMQ1_SIZE_IN_BYTES/sizeof(unsigned int)
#define REF_IQMP_SIZE_IN_UINT REF_IQMP_SIZE_IN_BYTES/sizeof(unsigned int)

typedef struct _ref_rsa_params_t {
unsigned int n[REF_N_SIZE_IN_UINT];
unsigned int e[REF_E_SIZE_IN_UINT];
unsigned int d[REF_D_SIZE_IN_UINT];
unsigned int p[REF_P_SIZE_IN_UINT];
unsigned int q[REF_Q_SIZE_IN_UINT];
unsigned int dmp1[REF_DMP1_SIZE_IN_UINT];
unsigned int dmq1[REF_DMQ1_SIZE_IN_UINT];
unsigned int iqmp[REF_IQMP_SIZE_IN_UINT];
}ref_rsa_params_t;

sgx_status_t entry_point(uint8_t *decrypted_ppid) {
sgx_status_t sgx_status = SGX_SUCCESS;
sgx_report_t id_enclave_report;
sgx_target_info_t pce_target_info;
sgx_report_data_t report_data = { 0 };

if (SGX_SUCCESS != (sgx_status = pce_get_target_info(&pce_target_info))) {
print_err_status("Failed to call in PPID: pce_get_target_info. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;

}

if ((pce_target_info.attributes.flags & SGX_FLAGS_PROVISION_KEY) != SGX_FLAGS_PROVISION_KEY ||
(pce_target_info.attributes.flags & SGX_FLAGS_DEBUG) != 0)
{
//PCE must have access to provisioning key
//Can't be debug PCE
print_err_status("PCE enclave can't be a DEBUG enclave. The error code is: 0x%04x.\n", SGX_ERROR_INVALID_PARAMETER);
goto CLEANUP;
}

uint32_t enc_key_size = REF_RSA_OAEP_3072_MOD_SIZE + REF_RSA_OAEP_3072_EXP_SIZE;
uint8_t enc_public_key[REF_RSA_OAEP_3072_MOD_SIZE + REF_RSA_OAEP_3072_EXP_SIZE];
ref_rsa_params_t g_rsa_key = { 0 };
g_rsa_key.e[0] = 0x10001;
pce_rsaoaep_3072_encrypt_pub_key_t* p_rsa_pub_key = (pce_rsaoaep_3072_encrypt_pub_key_t*)enc_public_key;

sgx_status = sgx_create_rsa_key_pair(REF_RSA_OAEP_3072_MOD_SIZE,
REF_RSA_OAEP_3072_EXP_SIZE,
(unsigned char*)g_rsa_key.n,
(unsigned char*)g_rsa_key.d,
(unsigned char*)g_rsa_key.e,
(unsigned char*)g_rsa_key.p,
(unsigned char*)g_rsa_key.q,
(unsigned char*)g_rsa_key.dmp1,
(unsigned char*)g_rsa_key.dmq1,
(unsigned char*)g_rsa_key.iqmp);
if (sgx_status != SGX_SUCCESS) {
print_err_status("Failed to create RSA key in sgx_create_rsa_key_pair. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

// PCE wants the key in big endian
size_t i;
uint8_t* p_temp;
p_temp = (uint8_t*)g_rsa_key.e;
for (i = 0; i < REF_RSA_OAEP_3072_EXP_SIZE; i++) {
p_rsa_pub_key->e[i] = *(p_temp + REF_RSA_OAEP_3072_EXP_SIZE - 1 - i); //create big endian e
}
p_temp = (uint8_t*)g_rsa_key.n;
for (i = 0; i < REF_RSA_OAEP_3072_MOD_SIZE; i++) {
p_rsa_pub_key->n[i] = *(p_temp + REF_RSA_OAEP_3072_MOD_SIZE - 1 - i); //create big endian n
}

sgx_sha_state_handle_t sha_handle = NULL;
uint8_t crypto_suite = PCE_ALG_RSA_OAEP_3072;
do {
sgx_status = sgx_sha256_init(&sha_handle);
if (SGX_SUCCESS != sgx_status)
break;

sgx_status = sgx_sha256_update(&crypto_suite,
sizeof(uint8_t),
sha_handle);
if (SGX_SUCCESS != sgx_status)
break;
//(MOD followed by e)
sgx_status = sgx_sha256_update(p_rsa_pub_key->n,
sizeof(p_rsa_pub_key->n),
sha_handle);
if (SGX_SUCCESS != sgx_status)
break;
sgx_status = sgx_sha256_update(p_rsa_pub_key->e,
sizeof(p_rsa_pub_key->e),
sha_handle);
if (SGX_SUCCESS != sgx_status)
break;
sgx_status = sgx_sha256_get_hash(sha_handle, (sgx_sha256_hash_t *)&report_data);
} while (0);
if (SGX_SUCCESS != sgx_status) {
if (SGX_ERROR_OUT_OF_MEMORY != sgx_status)
sgx_status = SGX_ERROR_UNEXPECTED;
print_err_status("Unexpected error when hashing with sgx_sha256. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

sgx_status = sgx_create_report(&pce_target_info, &report_data, &id_enclave_report);
if (SGX_SUCCESS != sgx_status && SGX_ERROR_OUT_OF_MEMORY != sgx_status) {
print_err_status("Unexpected error when creating sgx report in sgx_create_report. The error code is: 0x%04x.\n", sgx_status);
sgx_status = SGX_ERROR_UNEXPECTED;
goto CLEANUP;
}

uint8_t encrypted_ppid[REF_RSA_OAEP_3072_MOD_SIZE];
uint32_t encrypted_ppid_ret_size;
pce_info_t pce_info;
uint8_t signature_scheme;

unsigned int ret_val = 0;
sgx_status = get_encrypted_ppid(&ret_val, &id_enclave_report,
enc_public_key,
enc_key_size,
PCE_ALG_RSA_OAEP_3072,
encrypted_ppid,
REF_RSA_OAEP_3072_MOD_SIZE,
&encrypted_ppid_ret_size,
&pce_info,
&signature_scheme);

if (SGX_SUCCESS != ret_val) {
print_err_status("PCE.pce_get_pc_info finished with failure. The error code is: 0x%04x.\n", ret_val);
goto CLEANUP;
}

if (SGX_SUCCESS != sgx_status) {
print_err_status("Failed to call into the PCE: pce_get_pc_info. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

if (signature_scheme != PCE_NIST_P256_ECDSA_SHA256) {
sgx_status = -1;
print_err_status("PCE returned incorrect signature scheme.\n", sgx_status);
goto CLEANUP;
}

if (encrypted_ppid_ret_size != REF_RSA_OAEP_3072_MOD_SIZE) {
sgx_status = -1;
print_err_status("PCE returned incorrect encrypted PPID size.\n", sgx_status);
goto CLEANUP;
}

// Decrypt the PPID with the RSA private key generated with the new key and store it in the blob
// Create a private key context
void *rsa_key = NULL;
sgx_status = sgx_create_rsa_priv2_key(REF_RSA_OAEP_3072_MOD_SIZE,
REF_E_SIZE_IN_BYTES,
(const unsigned char*)g_rsa_key.e,
(const unsigned char*)g_rsa_key.p,
(const unsigned char*)g_rsa_key.q,
(const unsigned char*)g_rsa_key.dmp1,
(const unsigned char*)g_rsa_key.dmq1,
(const unsigned char*)g_rsa_key.iqmp,
&rsa_key);

if (sgx_status != SGX_SUCCESS) {
print_err_status("Failed to create RSA private key in sgx_create_rsa_priv2_key. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

size_t ppid_size = 0;
sgx_status = sgx_rsa_priv_decrypt_sha256(rsa_key,
NULL,
(&ppid_size),
encrypted_ppid,
REF_RSA_OAEP_3072_MOD_SIZE);

if (sgx_status != SGX_SUCCESS) {
print_err_status("Failed to compute size of decrypted ppid in sgx_rsa_priv_decrypt_sha256. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

sgx_status = sgx_rsa_priv_decrypt_sha256(rsa_key,
decrypted_ppid,
(&ppid_size),
encrypted_ppid,
REF_RSA_OAEP_3072_MOD_SIZE);

if (sgx_status != SGX_SUCCESS) {
print_err_status("Failed to decrypt ppid in sgx_rsa_priv_decrypt_sha256. The error code is: 0x%04x.\n", sgx_status);
goto CLEANUP;
}

CLEANUP:
// Clear critical output data on error
if (SGX_SUCCESS != sgx_status) {
memset_s(&id_enclave_report, sizeof(id_enclave_report), 0, sizeof(id_enclave_report));
}
if (sha_handle != NULL) {
sgx_sha256_close(sha_handle);
}

return sgx_status;
}
15 changes: 15 additions & 0 deletions intel-sgx/ppid-retrieval-tool/Enclave/ppid.config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<EnclaveConfiguration>
<IntelSigned>0</IntelSigned>
<ProvisionKey>0</ProvisionKey>
<ProdID>0x1</ProdID>
<ISVSVN>1</ISVSVN>
<TCSNum>1</TCSNum>
<TCSPolicy>1</TCSPolicy>
<HW>0</HW>
<StackMaxSize>0x20000</StackMaxSize>
<StackMinSize>0x20000</StackMinSize>
<HeapInitSize>0x100000</HeapInitSize>
<HeapMinSize>0x1000</HeapMinSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<DisableDebug>0</DisableDebug>
</EnclaveConfiguration>
Loading

0 comments on commit 6dafc6c

Please sign in to comment.