Add enclave debuggable verification for ra_tls

This commit is contained in:
Zheng, Qi 2022-03-09 14:32:44 +08:00 committed by Zongmin.Gu
parent 2d7fbefcc2
commit f4665dac11
8 changed files with 45 additions and 124 deletions

@ -55,7 +55,7 @@ If musl-libc version is expected.
./build_and_install.sh musl ./build_and_install.sh musl
``` ```
The following command will generate the client and server occlum images. It automatically parses the mr_enclave and mr_signer of the client, and write the value into dynamic_config.json. If you want to verify the other measurements of client, please modify the dynamic_config.json before run the script. The following command will generate the client and server occlum images. It automatically parses the mr_enclave and mr_signer of the client, and write the value into dynamic_config.json. If you want to verify the other measurements of client, please modify the `ra_config_template.json` before run the script.
``` ```
./build_occlum_instance.sh ./build_occlum_instance.sh
``` ```

@ -16,7 +16,8 @@ function build_instance() {
mkdir occlum_$postfix mkdir occlum_$postfix
pushd occlum_$postfix pushd occlum_$postfix
occlum init occlum init
new_json="$(jq '.resource_limits.user_space_size = "500MB"' Occlum.json)" && \ new_json="$(jq '.resource_limits.user_space_size = "500MB" |
.metadata.debuggable = false' Occlum.json)" && \
echo "${new_json}" > Occlum.json echo "${new_json}" > Occlum.json
if [ "$postfix" == "server" ]; then if [ "$postfix" == "server" ]; then
@ -25,8 +26,10 @@ function build_instance() {
.verify_mr_signer = "on" | .verify_mr_signer = "on" |
.verify_isv_prod_id = "off" | .verify_isv_prod_id = "off" |
.verify_isv_svn = "off" | .verify_isv_svn = "off" |
.verify_enclave_debuggable = "on" |
.sgx_mrs[0].mr_enclave = ''"'`get_mr client mr_enclave`'" | .sgx_mrs[0].mr_enclave = ''"'`get_mr client mr_enclave`'" |
.sgx_mrs[0].mr_signer = ''"'`get_mr client mr_signer`'" ' ../ra_config_template.json > dynamic_config.json .sgx_mrs[0].mr_signer = ''"'`get_mr client mr_signer`'" |
.sgx_mrs[0].debuggable = false ' ../ra_config_template.json > dynamic_config.json
if [ "$libnss_require" == "y" ]; then if [ "$libnss_require" == "y" ]; then
cp /lib/x86_64-linux-gnu/libnss*.so.2 image/$occlum_glibc cp /lib/x86_64-linux-gnu/libnss*.so.2 image/$occlum_glibc
@ -35,11 +38,13 @@ function build_instance() {
bomfile="../grpc_ratls_server.yaml" bomfile="../grpc_ratls_server.yaml"
else else
# Client verify nothing from server # Client verify only enclave non-debuggable from server
jq ' .verify_mr_enclave = "off" | jq ' .verify_mr_enclave = "off" |
.verify_mr_signer = "off" | .verify_mr_signer = "off" |
.verify_isv_prod_id = "off" | .verify_isv_prod_id = "off" |
.verify_isv_svn = "off" ' ../ra_config_template.json > dynamic_config.json .verify_isv_svn = "off" |
.verify_enclave_debuggable = "on" |
.sgx_mrs[0].debuggable = false ' ../ra_config_template.json > dynamic_config.json
bomfile="../grpc_ratls_client.yaml" bomfile="../grpc_ratls_client.yaml"
fi fi
@ -52,9 +57,9 @@ function build_instance() {
} }
if [[ $1 == "musl" ]]; then if [[ $1 == "musl" ]]; then
echo "*** Build and musl-libc Occlum instance ***" echo "*** Build musl-libc Occlum instance ***"
else else
echo "*** Build and run glibc Occlum instance ***" echo "*** Build glibc Occlum instance ***"
# glibc version requires libnss # glibc version requires libnss
libnss_require="y" libnss_require="y"
occlum_glibc=/opt/occlum/glibc/lib/ occlum_glibc=/opt/occlum/glibc/lib/

@ -1,68 +0,0 @@
#include "sgx_ra_tls_utils.h"
#include "sgx_ra_tls_backend.h"
#include "sgx_quote_3.h"
#include "occlum_dcap.h"
namespace grpc {
namespace sgx {
int verify_quote (uint8_t * quote_buffer, size_t quote_size) {
void *handle;
handle = dcap_quote_open();
uint32_t supplemental_size, ret;
uint8_t *p_supplemental_buffer;
sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED;
uint32_t collateral_expiration_status = 1;
supplemental_size = dcap_get_supplemental_data_size(handle);
p_supplemental_buffer = (uint8_t *)malloc(supplemental_size);
if (NULL == p_supplemental_buffer) {
printf("Couldn't allocate supplemental buffer\n");
}
memset(p_supplemental_buffer, 0, supplemental_size);
ret = dcap_verify_quote(
handle,
quote_buffer,
quote_size,
&collateral_expiration_status,
&quote_verification_result,
supplemental_size,
p_supplemental_buffer
);
if (0 != ret) {
printf( "Error in dcap_verify_quote.\n");
}
if (collateral_expiration_status != 0) {
printf("the verification collateral has expired\n");
}
dcap_quote_close(handle);
}
int generate_quote(uint8_t *quote_buffer, unsigned char *hash, size_t hash_len) {
void *handle;
handle = dcap_quote_open();
sgx_report_data_t report_data = { 0 };
memcpy(report_data.d, hash, hash_len);
// Get the Quote
int ret = dcap_generate_quote(handle, quote_buffer, &report_data);
if (0 != ret) {
printf( "Error in dcap_generate_quote.\n");
}
dcap_quote_close(handle);
return ret;
}
uint32_t get_quote_size() {
void *handle = dcap_quote_open();
uint32_t quote_size = dcap_get_quote_size(handle);
dcap_quote_close(handle);
return quote_size;
}
}//namespace grpc
}//namesapce sgx

@ -1,41 +0,0 @@
/*
*
* Copyright 2019 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef SGX_RA_TLS_BACKEND_H
#define SGX_RA_TLS_BACKEND_H
#include <string>
#include <memory>
#include <sstream>
namespace grpc {
namespace sgx {
int verify_quote (uint8_t * quote_buffer, size_t quote_size);
int generate_quote(uint8_t *quote_buffer, unsigned char *hash, size_t hash_len);
uint32_t get_quote_size();
}
}
#endif // SGX_RA_TLS_BACKEND_H

@ -65,6 +65,8 @@ static sgx_config parse_sgx_config_json(const char* file) {
sgx_cfg.verify_mr_signer = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_mr_signer"), "on"); sgx_cfg.verify_mr_signer = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_mr_signer"), "on");
sgx_cfg.verify_isv_prod_id = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_prod_id"), "on"); sgx_cfg.verify_isv_prod_id = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_prod_id"), "on");
sgx_cfg.verify_isv_svn = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_svn"), "on"); sgx_cfg.verify_isv_svn = sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_isv_svn"), "on");
sgx_cfg.verify_enclave_debuggable =
sgx_json.compare_item(sgx_json.get_item(sgx_json.get_handle(), "verify_enclave_debuggable"), "on");
auto objs = sgx_json.get_item(sgx_json.get_handle(), "sgx_mrs"); auto objs = sgx_json.get_item(sgx_json.get_handle(), "sgx_mrs");
auto obj_num = std::min(cJSON_GetArraySize(objs), SGX_MESUREMENTS_MAX_SIZE); auto obj_num = std::min(cJSON_GetArraySize(objs), SGX_MESUREMENTS_MAX_SIZE);
@ -86,6 +88,11 @@ static sgx_config parse_sgx_config_json(const char* file) {
auto isv_svn = sgx_json.print_item(sgx_json.get_item(obj, "isv_svn")); auto isv_svn = sgx_json.print_item(sgx_json.get_item(obj, "isv_svn"));
sgx_cfg.sgx_mrs[i].isv_svn = strtoul(isv_svn, nullptr, 10); sgx_cfg.sgx_mrs[i].isv_svn = strtoul(isv_svn, nullptr, 10);
if (cJSON_IsTrue(sgx_json.get_item(obj, "debuggable")) == 0)
sgx_cfg.sgx_mrs[i].debuggable = false;
else
sgx_cfg.sgx_mrs[i].debuggable = true;
}; };
return sgx_cfg; return sgx_cfg;
} }
@ -104,7 +111,8 @@ void ra_tls_verify_init() {
} }
static bool verify_measurement_internal(const char* mr_enclave, const char* mr_signer, static bool verify_measurement_internal(const char* mr_enclave, const char* mr_signer,
const char* isv_prod_id, const char* isv_svn) { const char* isv_prod_id, const char* isv_svn,
bool debuggable) {
bool status = false; bool status = false;
auto & sgx_cfg = _ctx_.sgx_cfg; auto & sgx_cfg = _ctx_.sgx_cfg;
for (auto & obj : sgx_cfg.sgx_mrs) { for (auto & obj : sgx_cfg.sgx_mrs) {
@ -130,6 +138,11 @@ static bool verify_measurement_internal(const char* mr_enclave, const char* mr_s
status = false; status = false;
} }
if (status && sgx_cfg.verify_enclave_debuggable && \
(obj.debuggable != debuggable)) {
status = false;
}
if (status) { if (status) {
break; break;
} }
@ -138,17 +151,19 @@ static bool verify_measurement_internal(const char* mr_enclave, const char* mr_s
} }
int verify_measurement(const char* mr_enclave, const char* mr_signer, int verify_measurement(const char* mr_enclave, const char* mr_signer,
const char* isv_prod_id, const char* isv_svn) { const char* isv_prod_id, const char* isv_svn,
bool debuggable) {
std::lock_guard<std::mutex> lock(_ctx_.mtx); std::lock_guard<std::mutex> lock(_ctx_.mtx);
bool status = false; bool status = false;
try { try {
assert(mr_enclave && mr_signer && isv_prod_id && isv_svn); assert(mr_enclave && mr_signer && isv_prod_id && isv_svn);
status = verify_measurement_internal(mr_enclave, mr_signer, isv_prod_id, isv_svn); status = verify_measurement_internal(mr_enclave, mr_signer, isv_prod_id, isv_svn, debuggable);
grpc_printf("remote sgx measurements\n"); grpc_printf("remote sgx measurements\n");
grpc_printf(" |- mr_enclave : %s\n", byte_to_hex(mr_enclave, 32).c_str()); grpc_printf(" |- mr_enclave : %s\n", byte_to_hex(mr_enclave, 32).c_str());
grpc_printf(" |- mr_signer : %s\n", byte_to_hex(mr_signer, 32).c_str()); grpc_printf(" |- mr_signer : %s\n", byte_to_hex(mr_signer, 32).c_str());
grpc_printf(" |- isv_prod_id : %hu\n", *((uint16_t*)isv_prod_id)); grpc_printf(" |- isv_prod_id : %hu\n", *((uint16_t*)isv_prod_id));
grpc_printf(" |- isv_svn : %hu\n", *((uint16_t*)isv_svn)); grpc_printf(" |- isv_svn : %hu\n", *((uint16_t*)isv_svn));
grpc_printf(" |- debuggable : %s", debuggable?"true":"false");
if (status) { if (status) {
grpc_printf(" |- verify result : success\n"); grpc_printf(" |- verify result : success\n");
} else { } else {

@ -50,6 +50,7 @@ struct sgx_measurement {
char mr_signer[32]; char mr_signer[32];
uint16_t isv_prod_id; uint16_t isv_prod_id;
uint16_t isv_svn; uint16_t isv_svn;
bool debuggable;
}; };
struct sgx_config { struct sgx_config {
@ -57,6 +58,7 @@ struct sgx_config {
bool verify_mr_signer = true; bool verify_mr_signer = true;
bool verify_isv_prod_id = true; bool verify_isv_prod_id = true;
bool verify_isv_svn = true; bool verify_isv_svn = true;
bool verify_enclave_debuggable = true;
std::vector<sgx_measurement> sgx_mrs; std::vector<sgx_measurement> sgx_mrs;
}; };
@ -97,7 +99,8 @@ void ra_tls_parse_sgx_config(const char* file);
void ra_tls_verify_init(); void ra_tls_verify_init();
int verify_measurement(const char* mr_enclave, const char* mr_signer, int verify_measurement(const char* mr_enclave, const char* mr_signer,
const char* isv_prod_id, const char* isv_svn); const char* isv_prod_id, const char* isv_svn,
bool debuggable);
void credential_option_set_certificate_provider(grpc::sgx::CredentialsOptions& options); void credential_option_set_certificate_provider(grpc::sgx::CredentialsOptions& options);

@ -299,10 +299,16 @@ int occlum_verify_cert(const unsigned char * der_crt, size_t len) {
return -1; return -1;
} }
// Check if enclave is debuggable
bool debuggable = false;
if (p_rep_body->attributes.flags & SGX_FLAGS_DEBUG)
debuggable = true;
ret = verify_measurement((const char *)&p_rep_body->mr_enclave, ret = verify_measurement((const char *)&p_rep_body->mr_enclave,
(const char *)&p_rep_body->mr_signer, (const char *)&p_rep_body->mr_signer,
(const char *)&p_rep_body->isv_prod_id, (const char *)&p_rep_body->isv_prod_id,
(const char *)&p_rep_body->isv_svn); (const char *)&p_rep_body->isv_svn,
debuggable);
if (ret != 0) { if (ret != 0) {
grpc_printf("verify the measurement failed!\n"); grpc_printf("verify the measurement failed!\n");
return -1; return -1;

@ -3,13 +3,14 @@
"verify_mr_signer" : "on", "verify_mr_signer" : "on",
"verify_isv_prod_id" : "on", "verify_isv_prod_id" : "on",
"verify_isv_svn" : "on", "verify_isv_svn" : "on",
"verify_enclave_debuggable" : "on",
"sgx_mrs": [ "sgx_mrs": [
{ {
"mr_enclave" : "", "mr_enclave" : "",
"mr_signer" : "", "mr_signer" : "",
"isv_prod_id" : "0", "isv_prod_id" : "0",
"isv_svn" : "0" "isv_svn" : "0",
"debuggable" : false
} }
], ]
"other" : []
} }